/*! BUI - v2.0.0 - 2022-03-13 09:03:17 
Copyright (c): kevin.huang  https://gitee.com/kevin-huang/bui2.0.git (qq:757723114) 
Released under MIT License*/
(function ( global, factory) {
//   "use strict";
	if ( typeof module === "object" && typeof module.exports === "object" ) {
		module.exports = global.document ?
			factory( global, true ) :
			function( w ) {
				if ( !w.document ) {
					throw new Error( "Bui requires a window with a document" );
				}
				return factory( w );
			};
	} else {
		  factory( global );
	}  
})( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
//   "use strict";
  var $B = window["$B"] ?  window["$B"] : {};

var $body, DomUtils,_onNodeRemoveEventTimer;
function _getBody() {
    if (!$body) {
        $body = document.body;
        $B.DomUtils.css($body, { "position": "relative" });
    }
    return $body;
}
$B["getBody"] = _getBody;

var class2type = {},
    hasOwn = class2type.hasOwnProperty,
    toString = class2type.toString;

/***
 * 获取数据类型
 * ***/
function getDataType(obj) {
    var toString = Object.prototype.toString;
    var map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        '[object Array]': 'array',
        '[object Date]': 'date',
        '[object RegExp]': 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]': 'null',
        '[object Object]': 'object'
    };
    if (obj instanceof Element) {
        return 'element';
    }
    return map[toString.call(obj)];
}
$B["getDataTypeFn"] = getDataType;

/****
 * 确保是数组
 * ******/
function ensureArray(data) {
    if (Array.isArray(data)) {
        return data;
    }
    return [data];
}
$B["ensureArrayFn"] = ensureArray;


function _isInArray(elem, arr, i) {
    var len;
    if (arr) {
        if (Array.prototype.indexOf) {
            return Array.prototype.indexOf.call(arr, elem, i);
        }
        len = arr.length;
        i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
        for (; i < len; i++) {
            if (i in arr && arr[i] === elem) {
                return i;
            }
        }
    }
    return -1;
}
$B["isInArrayFn"] = _isInArray;

function _diyTrim(str) {
    var trimLeft = /^\s+/,
        trimRight = /\s+$/,
        rnotwhite = /\S/;
    if (rnotwhite.test("\xA0")) {
        trimLeft = /^[\s\xA0]+/;
        trimRight = /[\s\xA0]+$/;
    }
    return str == null ? "" : str.replace(trimLeft, "").replace(trimRight, "");
}

function _trim(str) {
    var r;
    if (String.prototype.trim) {
        r = str.trim();
    } else {
        r = _diyTrim(str);
    }
    r = r.replace(/\u200B/g, '');
    return r;
}

$B["trimFn"] = _trim;

// 变成驼峰
function camelFn(str) {
    return str.replace(/-(\w)/g, function (m0, m1) {
        return m1.toUpperCase();
    });
}
// 变成破折
function dashesFn(str) {
    return str.replace(/[A-Z]/g, function (m0) {
        return '-' + m0.toLowerCase();
    });
}
$B["camelFn"] = camelFn;
$B["dashesFn"] = dashesFn;

/**
 * 返回obj元素在array中的位置
 * @param {Array} array
 * @param {*} obj
 * @returns {number}
 * @private
 */
function _indexOf(array, obj) {
    if (Array.prototype.indexOf) {
        return Array.prototype.indexOf.call(array, obj);
    }
    for (var i = 0, j = array.length; i < j; i++) {
        if (array[i] === obj) {
            return i;
        }
    }
    return -1;
}
$B["indexOfArrayFn"] = _indexOf;
/**
 * 是否是数组
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isArray(object) {
    return Object.prototype.toString.call(object) === '[object Array]';
}
$B["isArrayFn"] = _isArray;
/**
 *是否是字符串
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isString(object) {
    return typeof object === 'string';
}
$B["isStringFn"] = _isString;
/**
 * 是否是数字
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isNumeric(object) {
    var ret = typeof object === 'number' && isFinite(object);
    if (!ret) {
        var regPos = /^\d+(\.\d+)?$/; //非负浮点数
        var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
        if (regPos.test(object) && regNeg.test(object)) {
            ret = true;
        } else {
            ret = false;
        }
    }
    return ret;
}
$B["isNumericFn"] = _isNumeric;
/**
 * 是否是object对象
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isObject(object) {
    return typeof object === 'object';
}

function _isEmptyObject(object) {
    if (_isObject(object)) {
        return Object.keys(object).length === 0;
    }
    return false;
}
$B["isEmptyObjectFn"] = _isEmptyObject;

/**
 * 检查是否是函数
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isFunction(object) {
    return typeof object === 'function';
}
$B["isFunctionFn"] = _isFunction;
/**
 * 检查是否是{}对象
 * @param object
 * @returns {*|boolean}
 * @private
 */
function _isLiteralObject(obj) {
    var key;
    if (!obj || typeof obj !== "object" || obj.nodeType) {
        return false;
    }
    try {
        if (obj.constructor &&
            !hasOwn.call(obj, "constructor") &&
            !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
            return false;
        }
    } catch (e) {
        return false;
    }
    for (key in obj) {
    }
    return key === undefined || hasOwn.call(obj, key);
    //return object && typeof object === "object" && Object.getPrototypeOf(object) === Object.getPrototypeOf({});
}
$B["isPlainObjectFn"] = _isLiteralObject;

/**
 * 检查是否是可迭代的元素
 * @param {Object} object
 * @returns {boolean}
 * @private
 */
function _isIterable(object) {
    if (object instanceof HTMLElement 
        || object instanceof Node || (typeof object === 'object' && object.nodeName && object.tagName)) {
        return false;
    }
    var r = _isLiteralObject(object) || _isArray(object) || (typeof object === 'object' && object !== null && object['length'] !== undefined);
    return r;
}
$B["isIterableFn"] = _isIterable;

/**
 * 深拷贝克隆一个对象
 * @param {Object} object
 * @private
 */
function _cloneObject(object) {
    var copy;
    var property;
    if (!_isObject(object) || object === null) {
        copy = object;
        return copy;
    }
    if (_isArray(object)) {
        copy = [];
        for (var i = 0, l = object.length; i < l; i++) {
            copy[i] = _cloneObject(object[i]);
        }
        return copy;
    }
    copy = {};
    for (property in object) {
        if (!object.hasOwnProperty(property)) {
            continue;
        }
        if (_isObject(object[property]) && object[property] !== null) {
            copy[property] = _cloneObject(object[property]);
        } else {
            copy[property] = object[property];
        }
    }
    return copy;
}
$B["cloneObjectFn"] = _cloneObject;



/****
 * 对象合并 ：将srcObj拷贝到destObj上
 * destObj:合并到的对象
 * srcObj：合并的来源对象
 * notOverride:不覆盖已经存在的key destObj, srcObj, notOverride
 * ******/
function _extendObjectFn() {
    var src, copyIsArray, copy, name, options, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    if (typeof target === "boolean") {
        deep = target;
        target = arguments[i] || {};
        i++;
    }

    if (typeof target !== "object" && typeof target !== "function") {
        target = {};
    }

    if (i === length) {
        target = this;
        i--;
    }

    for (; i < length; i++) {
        if ((options = arguments[i])) {
            for (name in options) {
                if (!options.hasOwnProperty(name)) {
                    continue;
                }
                src = target[name];
                copy = options[name];
                if (target === copy) {
                    continue;
                }
                if (deep && copy && (_isLiteralObject(copy) || (copyIsArray = _isArray(copy)))) {
                    if (copyIsArray) {
                        copyIsArray = false;
                        clone = src && _isArray(src) ? src : [];

                    } else {
                        clone = src && _isLiteralObject(src) ? src : {};
                    }
                    target[name] = _extendObjectFn(deep, clone, copy);

                } else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }
    return target;
}
$B["extendObjectFn"] = _extendObjectFn;

function needReplacePx(prop) {
    prop = prop.toLowerCase();
    if(prop.indexOf("border") >= 0 && prop.indexOf("width") < 0){
        return false;
    }
    if (prop.indexOf("width") > -1 || prop.indexOf("height") > -1 
    || prop.indexOf("top") > -1 || prop.indexOf("left") > -1 
    || prop.indexOf("padding") > -1 || prop.indexOf("margin") > -1
    ) {
        return true;
    }
    return false;
}
/**
 * 获取样式的style样式
 * @param element
 * @param prop
 * @returns {*}
 * @private
 */
function _getComputedStyle(element, prop) {
    var computedStyle;
    if (typeof window.getComputedStyle === 'function') { //normal browsers
        computedStyle = window.getComputedStyle(element);
    } else if (typeof document.currentStyle !== undefined) { //shitty browsers
        computedStyle = element.currentStyle;
    } else {
        computedStyle = element.style;
    }
    if (prop) {
        let value = computedStyle[prop];
        if (needReplacePx(prop)) {
            if(value.indexOf("px") > 0){
                value = parseFloat(value.replace("px", ""));
            }else if(/^-?\d+(.?\d+)?$/.test(value)){
                value = parseFloat(value);
            }
        }
        return value;
    } else {
        return computedStyle;
    }
}
$B["getComputedStyleFn"] = _getComputedStyle;
/**
 * 循环对象object
 * @param object
 * @param callback
 * @private
 */
function _each(object, callback) {
    var i, l;
    if (_isArray(object) || (typeof object === 'object' && object['length'] !== undefined)) {
        for (i = 0, l = object.length; i < l; i++) {
            callback.apply(object[i], [object[i], i]);
        }
        return;
    }
    if (_isLiteralObject(object)) {
        var keys = Object.keys(object);
        for (i = 0; i < keys.length; i++) {
            callback.apply(object[keys[i]], [object[keys[i]], keys[i]]);
        }
    }
}
$B["foreachFn"] = _each;

var _domReadyHandlers = [];
var _domLoadedHandlers = [];
var _isDomReady = false;
var _isDomLoaded = false;
var _animationLastTime;
/**这些属性不自动添加px单位**/
var CSSNumber = {
    "animationIterationCount": true,
    "animation-iteration-count": true,
    "columnCount": true,
    "column-count": true,
    "fillOpacity": true,
    "fill-opacity": true,
    "flexGrow": true,
    "flex-grow": true,
    "flexShrink": true,
    "flex-shrink": true,
    "opacity": true,
    "order": true,
    "orphans": true,
    "widows": true,
    "zIndex": true,
    "z-index": true,
    "zoom": true,
    "WebkitLineClamp":true,    
    "-webkit-line-clamp": true
};
var addListener = document.addEventListener ? 'addEventListener' : 'attachEvent';
var removeListener = document.removeEventListener ? 'removeEventListener' : 'detachEvent';
var eventPrefix = document.addEventListener ? '' : 'on';
var createEvent = document.createEvent ? 'createEvent' : 'createEventObject';
var dispatchEvent = document.dispatchEvent ? 'dispatchEvent' : 'fireEvent';
var vendors = ['-moz-', '-ms-', '-webkit-', '-o-', ''];
var cssMap = {
    "background-color":"backgroundColor",
    "z-index":"zIndex"  
};
var cssNameProperty = function (prop) { 
    var exp = /-([a-z0-9])/;
    while (exp.test(prop)) {
        prop = prop.replace(exp, RegExp.$1.toUpperCase());
    }
    return prop;
};
var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame || window.cancelRequestAnimationFrame;
var div = document.createElement('div');
var style = _getComputedStyle(div);

//ie版本
var ie = (function () {
    var rv;
    if (navigator.appName === 'Microsoft Internet Explorer') {
        var ua = navigator.userAgent;
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null) {
            rv = parseFloat(RegExp.$1);
        }
    }
    return rv;
}());

//transition detection
var transitionSupport = (function () {
    for (var i in vendors) {
        if (_isString(style[vendors[i] + 'transition'])) {
            return true;
        }
    }
    return false;
})();

//request animation pollyfill
if (!requestAnimationFrame || !cancelAnimationFrame) {
    for (var i = 0; i < vendors.length; i++) {
        var vendor = vendors[i];
        requestAnimationFrame = requestAnimationFrame || window[vendor + 'RequestAnimationFrame'];
        cancelAnimationFrame = cancelAnimationFrame || window[vendor + 'CancelAnimationFrame'] || window[vendor + 'CancelRequestAnimationFrame'];
    }
}

if (!requestAnimationFrame || !cancelAnimationFrame) {
    requestAnimationFrame = function (callback) {
        var currentTime = new Date().getTime();
        var timeToCall = Math.max(0, 16 - (currentTime - _animationLastTime));
        var id = window.setTimeout(function _requestAnimationFrameTimeout() {
            callback(currentTime + timeToCall);
        }, timeToCall);

        _animationLastTime = currentTime + timeToCall;
        return id;
    };

    cancelAnimationFrame = function (id) {
        window.clearTimeout(id);
    };
}

function _getOffset(elem) {
    var docElem, win,
        box = { top: 0, left: 0 },
        doc = elem && elem.ownerDocument;//当前文档
    if (!doc) {
        return;
    }
    docElem = doc.documentElement;
    if (typeof elem.getBoundingClientRect !== 'undefined') {//如果元素有getBoundingClientRect方法
        box = elem.getBoundingClientRect();//调用该方法
    }
    win = window;//如果是window就返回window，如果是document，返回document.defaultView
    return {
        //元素相对于视窗的距离+滚动距离-边框宽度
        top: box.top + win.pageYOffset - docElem.clientTop,
        left: box.left + win.pageXOffset - docElem.clientLeft
    };
}

var Mouse = {
    BUTTON_LEFT: 0,
    BUTTON_MIDDLE: 1,
    BUTTON_RIGHT: 2
};
//事件参数二次封装
function EventArgs(e) {
    this._e = e;
    if (!EventArgs.prototype.stopPropagation) {
        EventArgs.prototype.stopPropagation = function () {
            if (this._e.stopPropagation) {
                this._e.stopPropagation();
            } else {
                this._e.cancelBubble = true;
            }
        };
    }

    if (!EventArgs.prototype.stopPropagation) {
        EventArgs.prototype.preventDefault = function () {
            if (this._e.preventDefault) {
                this._e.preventDefault();
            } else {
                this._e.returnValue = false;
            }
        };
    }
    this.target = this._e.target || this._e.srcElement;
    this.ctrlKey = this._e.ctrlKey;
    this.shiftKey = this._e.shiftKey;
    this.altKey = this._e.altKey;
    this.layerY = this._e.layerY || this._e.offsetY;
    this.layerX = this._e.layerX || this._e.offsetX;
    this.x = this._e.x || this._e.clientX;
    this.y = this._e.y || this._e.clientY;
    this.pageX = this._e.pageX;
    this.pageY = this._e.pageY;
    this.keyCode = this._e.keyCode;
    this.name = this.type = this._e.type;
    this.path = this._e.path;    
    this.which = this._e.which;
    if (ie & ie < 9) {
        this.button = this._e.button === 1 ? Mouse.BUTTON_LEFT : (this._e.button === 4 ? Mouse.BUTTON_MIDDLE : Mouse.BUTTON_RIGHT);
    } else if (this._e.hasOwnProperty('which')) {
        this.button = this._e.which === 1 ? Mouse.BUTTON_LEFT : (this._e.which === 2 ? Mouse.BUTTON_MIDDLE : Mouse.BUTTON_RIGHT);
    } else {
        this.button = this._e.button;
    }
}
//dom事件机制封装
function commHandleEvent(event) {
    event = event || window.event;
    let handlers = this.events[event.type];
   
    if(_isEmptyObject(handlers)){        
        return;
    }
    var keys = Object.keys(handlers);
    let ret, handler,isEmpty = true;
    for (let i = 0; i < keys.length; i++) {
        handler = handlers[keys[i]];
        if(!handler){
            console.log("handler ex");
            continue; 
        }
        isEmpty = false;
        let ev = new EventArgs(event);
        ev.eventNamespace = handler.namespace;
        if (handler.params) {
            ev.params = handler.params;
        }
        let res;
        if (typeof handler.fn === "function") {
            ev.catpurer = this;
            res = handler.fn.call(this, ev);
        }
        if (typeof ret === "undefined" && typeof res !== "undefined") {
            ret = !res;
        }
    }
    if (ret) {//执行阻止冒泡
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
        event.returnValue = false; 
    }
    if(isEmpty){
        console.log("not events clear el");
        delete this.events[event.type];
    }
}

var radioCheckboxHooks = {
    set: function (elem, value) {
        if (Array.isArray(value)) {
            return "";
        }
    },
    get: function (elem) {
        return elem.getAttribute("value") === null ? "on" : elem.value;
    }
};
let regName = /^(\w+)\[(.+)\]$/;
function getNameAndAttr(arg1){
    let ret = {name:arg1};
    if(regName.test(arg1)){
        let math = regName.exec(arg1);
        ret.name = math[1];
        ret.attr = math[2];
    }
    return ret;
}
var valHooks = {
    option: {
        get: function (elem) {
            var val = elem.getAttribute("value");
            return val != null ? _trim(val) : _trim(elem.innerText);
        },
        set: function (elem, value) {
        }
    },
    select: {
        get: function (elem) {
            var value, option,
                options = elem.options,
                index = elem.selectedIndex,//当前选中项 单选默认0，多选默认-1
                //如果是单选下拉框或者当前没有选中项，one为true
                one = elem.type === "select-one" || index < 0,
                values = one ? null : [],//one为true，则values为null，否则为[]
                max = one ? index + 1 : options.length,//单选最大为1,多选为options.length
                i = index < 0 ?
                    max :
                    one ? index : 0;
            for (; i < max; i++) {//遍历
                option = options[i];
                if ((option.selected || i === index) && (typeof option.disabled !== "undefined" ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || option.parentNode.nodeName.toLowerCase() !== "optgroup")) {
                    value = valHooks.option.get(option);
                    if (one) {//单选直接返回
                        return value;
                    }
                    values.push(value);//多选推入数组
                }
            }
            return values;//多选且没有没有默认项，不经过循环直接返回
        },
        set: function (elem, value) {
            var optionSet, option,
                options = elem.options,
                values = ensureArray(value),//转为数组,value可以是任何值 "a"=>["a"]
                i = options.length;//选项数量
            //遍历
            while (i--) {
                option = options[i];
                //如果当前选项的值在values数组中，selected为true，否则为false
                //可以用于设置多选的下拉单值
                /*用法：
                    <select name="" id="" class="slt" multiple>
                        <option value="a">aaa</option>
                        <option value="b">bbbb</option>
                        <option value="c">ccccc</option>
                    </select>
                    <script>
                        $('.slt').val(["a","c"]);
                    </script>
                 */
                if ((option.selected = _isInArray(option.value, values) >= 0)) {
                    optionSet = true;//标识
                }
            }

            // force browsers to behave consistently when non-matching value is set
            if (!optionSet) {
                elem.selectedIndex = -1;
            }
            return values;
        }
    },
    radio: radioCheckboxHooks,
    checkbox: radioCheckboxHooks
};
var DomApiObj = {
    /***
     * 对元素添加一个事件监听
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * params:额外的参数
     * **/
    addListener: function (eventName, listener, params) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.addListener.call(element[i], eventName, listener, params);
            }
            return this;
        }
        if (!element.eventIndex) {
            element.eventIndex = 1;
        } else {
            element.eventIndex++;
        }
        if (!element.events) {
            element.events = {};
        }
        var namespace = "", eventKey = element.eventIndex;
        if (eventName.indexOf(".") > 0) {
            let arr = eventName.split(".");
            namespace = arr[0];
            eventName = arr[1];
        }
        let handlers = element.events[eventName];
        if (!handlers) {
            handlers = {};
            handlers[eventKey] = {
                params: params,
                namespace: namespace,
                fn: listener
            };
            if (element.addEventListener) {
                element.addEventListener(eventName, commHandleEvent, false);
            } else {
                element["on" + eventName] = commHandleEvent;
            }
            listener.eventIndex = element.eventIndex;
            element.events[eventName] = handlers;
        } else {
            //避免重复添加
            if (listener.eventIndex) {
                if (handlers[listener.eventIndex] && handlers[listener.eventIndex].fn === listener) {                   
                    return DomUtils;
                }
            }
            handlers[eventKey] = {
                params: params,
                namespace: namespace,
                fn: listener
            };
            listener.eventIndex = element.eventIndex;
        }
        return this;
    },
    /***
     * 对元素移除事件
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * **/
    removeListener: function (eventName, listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.removeListener.call(element[i], eventName, listener);
            }
            return this;
        }
        if (element.events) {
            if (typeof eventName !== "string") {
                return;
            }
            var namespace;
            if (eventName.indexOf(".") > 0) {
                let arr = eventName.split(".");
                namespace = arr[0];
                eventName = arr[1];
            }
            if (eventName === "*") {
                listener = undefined;
            }
            if (element.events[eventName] || (eventName === "*" && namespace)) {
                if (namespace) {//如果存在命名空间
                    let allEventNames = Object.keys(element.events); // click 、mousedown、mouseup、change............   
                    let i, j, eventMap, eventKeys, eventKey, handler;
                    for (i = 0; i < allEventNames.length; i++) {
                        if (eventName === "*" || eventName === allEventNames[i] || typeof listener === "undefined") {
                            eventMap = element.events[allEventNames[i]];//click 、mousedown、mouseup、change事件集合
                            eventKeys = Object.keys(eventMap);//eventindex
                            for (j = 0; j < eventKeys.length; j++) {
                                eventKey = eventKeys[j];
                                handler = eventMap[eventKey];
                                if (handler.namespace !== "") { //事件是存在命名空间的
                                    if (handler.namespace === namespace) {
                                        if (typeof listener === "undefined") {
                                            if (eventName === "*" || eventName === allEventNames[i]) {//移除命名空间下的所有事件
                                                delete eventMap[eventKey];
                                            }
                                        } else {
                                            if (eventName === allEventNames[i] && (listener.eventIndex + '') === eventKey) {
                                                delete eventMap[eventKey];
                                            }
                                        }
                                    }
                                }
                            }
                            if (_isEmptyObject(eventMap)) {
                                delete element.events[allEventNames[i]];
                                element.removeEventListener(allEventNames[i], commHandleEvent);//移除通用处理
                            }
                        }
                    }
                } else {
                    if (listener) {
                        delete element.events[eventName][listener.eventIndex];
                    } else {
                        element.events[eventName] = {};
                    }
                }
            }
            if (!element.events[eventName] || Object.keys(element.events[eventName]).length === 0) {
                delete element.events[eventName];
                element.removeEventListener(eventName, commHandleEvent);//移除通用处理
            }
        } else {
            element.removeEventListener(eventName, commHandleEvent);//移除通用处理
        }
        return this;
    },
    /***
     * 触发事件
     * ****/
    trigger: function (eventName, args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.trigger.call(element[i], eventName, args);
            }
            return this;
        }
        if (element.events) {
            var namespace = "";
            if (eventName.indexOf(".") > 0) {
                let arr = eventName.split(".");
                namespace = arr[0];
                eventName = arr[1];
            }
            let handlers = element.events[eventName];
            if(!handlers){
                return;
            }
            let keys = Object.keys(handlers);
            let pr = { target: element, isTrigger: true, params: {} };
            if (args) {
                Object.assign(pr, args);
            }
            for (let i = 0; i < keys.length; i++) {
                let evObj = handlers[keys[i]];
                if (namespace === "" || namespace === evObj.namespace) {
                    pr.params = evObj.params;
                    evObj.fn.call(element, pr);
                }
            }
        }
        return this;
    },
    /***
     * 解除element元素的某一类事件
     * eventName=click、mousedown、mouseup 事件名称或者 namespace.eventName 或者 namespace.*
     * ***/
    offEvents: function (eventName) {        
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.offEvents.call(element[i], eventName);
            }
            return this;
        }
        if (element.events) {
            if (eventName) {
                DomApiObj.removeListener.call(element, eventName);
            } else {
                var eventNames = Object.keys(element.events);
                for (var i = 0; i < eventNames.length; ++i) {
                    DomApiObj.removeListener.call(element, eventNames[i]);
                }
            }
        }
        return this;
    },
    /***
     * 批量绑定事件
     * events = {
     *      click:fn,
     *      dblclick:fn
     * }
     * ***/
    bind: function (events) {
        if (!_isLiteralObject(events)) {
            throw new Error("events is not a  object {}");
        }
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.bind.call(element[i], events);
            }
            return this;
        }
        let keys = Object.keys(events);
        for (let i = 0; i < keys.length; i++) {
            let eventName = keys[i];
            if (DomApiObj[eventName]) {
                DomApiObj[eventName].call(element, events[eventName]);
            }
        }
        return this;
    },
    click: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.click.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "click", listener);
        return this;
    },
    paste:function(listener){
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.paste.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "paste", listener);
        return this;
    },
    contextmenu: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.contextmenu.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "contextmenu", listener);
        return this;
    },
    dblclick: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.dblclick.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "dblclick", listener);
        return this;
    },
    mouseover: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseover.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseover", listener);
        return this;
    },
    mouseout: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseout.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseout", listener);
        return this;
    },
    mousedown: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mousedown.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mousedown", listener);
        return this;
    },
    mouseup: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseup.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseup", listener);
        return this;
    },
    mouseenter: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseenter.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseenter", listener);
        return this;
    },
    mouseleave: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseleave.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseleave", listener);
        return this;
    },
    mousemove: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mousemove.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mousemove", listener);
        return this;
    },
    touchstart: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchstart.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchstart", listener);
        return this;
    },
    touchend: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchend.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchend", listener);
        return this;
    },
    touchmove: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchmove.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchmove", listener);
        return this;
    },
    touchcancel: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchcancel.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchcancel", listener);
        return this;
    },
    focus: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.focus.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "focus", listener);
        return this;
    },
    blur: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.blur.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "blur", listener);
        return this;
    },
    select: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.select.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "select", listener);
        return this;
    },
    change: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.change.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "change", listener);
        return this;
    },
    submit: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.submit.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "submit", listener);
        return this;
    },
    reset: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.reset.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "reset", listener);
        return this;
    },
    onload: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.onload.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "load", listener);
        return this;
    },
    scroll: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.scroll.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "scroll", listener);
        return this;
    },
    unload: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.unload.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "unload", listener);
        return this;
    },
    resize: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.resize.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "resize", listener);
        return this;
    },
    keydown: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.keydown.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "keydown", listener);
        return this;
    },
    keyup: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.keyup.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "keyup", listener);
        return this;
    },
    keypress: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.keypress.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "keypress", listener);
        return this;
    },
    input:function(listener){
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.input.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "input", listener);
        return this;
    },
    /**
     * 是否是dom元素
     * @param {object} element
     * @returns {boolean}
     */
    isElement: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (typeof HTMLElement === 'object') {
            return element instanceof HTMLElement;
        }
        return element && typeof element === 'object' && element.nodeType === 1 && typeof element.nodeName === 'string';
    },
    /**
     * 是否是 DOMNode
     * @param node
     * @returns {*}
     */
    isNode: function () {
        var node = this;
        if (this._el) {
            node = this._el;
        }
        if (_isArray(node)) {
            node = node[0];
        }
        if (typeof Node === 'object') {
            return node instanceof Node;
        }
        return node && typeof node === 'object' && typeof node.nodeType === 'number' && typeof node.nodeName === 'string';
    },
    /***
     * 获取元素element，位置、高宽信息
     * ***/
    domInfo: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isElement.call(element)) {
            return false;
        }
        var rect = element.getBoundingClientRect();
        var info = {
            top: parseFloat(rect.top.toFixed(2)), //Math.round(rect.top)
            right: parseFloat(rect.right.toFixed(2)),
            bottom: parseFloat(rect.bottom.toFixed(2)),
            left: parseFloat(rect.left.toFixed(2)),
            width: rect.width ? parseFloat(rect.width.toFixed(2)) : parseFloat(element.offsetWidth.toFixed(2)),
            height: rect.height ? parseFloat(rect.height.toFixed(2)) : parseFloat(element.offsetHeight.toFixed(2))
        };
        if (info.width <= 0) {
            info.width = parseFloat(_getComputedStyle(element, 'width'));
        }
        if (info.height <= 0) {
            info.height = parseFloat(_getComputedStyle(element, 'height'));
        }
        let docElem = document.documentElement;
        let scrollTop = docElem.scrollTop;
        let scrollLeft = docElem.scrollLeft;
        info.pageTop = info.top + scrollTop;
        info.pageLeft = info.left + scrollLeft;
        info.scrollHeight = element.scrollHeight;
        info.scrollWidth = element.scrollWidth;
        info.offsetWidth = element.offsetWidth;
        info.offsetHeight = element.offsetHeight;
        info.pageScrollTop = scrollTop;
        info.pageScrollLeft = scrollLeft;
        info.elScrollTop = element.scrollTop;
        info.elScrollLeft = element.scrollTop;
        return info;
    },
    /*****
     * selector api 返回数组
     * element：元素
     * selector：刷选条件
     * *****/
    findBySelector: function (selector) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var result = [];
        if (DomApiObj.isNode.call(element)) {
            result = element.querySelectorAll(selector);
            result = Array.from(result);
        } else {
            result = document.querySelectorAll(selector);
            result = Array.from(result);
        }

        return result;
    },
    findById:function(args){
        return this.findbyId(args);
    },
    findByid:function(args){
        return this.findbyId(args);
    },
    /***
     * 根据id查找元素
     * arg1:id / dom元素
     * arg2:当arg1是dom时候，arg2为id
     * ***/
    findbyId: function (arg2) {
        var arg1 = this;
        if (this._el) {
            arg1 = this._el;
        }
        if (_isArray(arg1)) {
            arg1 = arg1[0];
        }
        if (typeof arg2 === "undefined") {
            if (arg1.substring(0, 1) === "#") {
                arg1 = arg2.substring(1);
            }
            return document.getElementById(arg1);
        } else {
            if (arg1.querySelector) {
                if (arg2.substring(0, 1) !== "#") {
                    arg2 = "#" + arg2;
                }
                return arg1.querySelector(arg2);
            } else {
                if (arg2.substring(0, 1) === "#") {
                    arg2 = arg2.substring(1);
                }
                return document.getElementById(arg1);
            }

        }
    },
    /***
     * 根据tag Name查询元素
     * arg1:name / dom元素
     * arg2:当arg1是dom时候，arg2为name
     * ***/
    findByTagName: function (arg2) {       
        var arg1 = this;
        if (this._el) {
            arg1 = this._el;
        }
        if (_isArray(arg1)) {
            arg1 = arg1[0];
        }
        let ret;
        let s;
        if (typeof arg2 === "undefined") {
            s = getNameAndAttr(arg1);
            ret = document.getElementsByTagName(s.name);           
        } else {
            s = getNameAndAttr(arg2);
            ret = arg1.querySelectorAll(s.name);
        }
        if(s.attr){
            let res = [];
            let arr = s.attr.split("=");
            let name = arr[0];
            let val = arr[1];
            for(let i =0 ; i < ret.length ;i++){
                let el = ret[i];
                if($B.DomUtils.attribute(el,name) === val){
                    res.push(el);
                }
            }
            ret = res;
        }else{
            ret = Array.from(ret);
        }
        return ret;
    },
    /***
     * 根据class查询元素
     * arg1：className / dom元素
     * arg2：当arg1是dom元素，arg2位className
     * ***/
    findByClass: function (arg2) {
        var arg1 = this;
        if (this._el) {
            arg1 = this._el;
        }
        if (_isArray(arg1)) {
            arg1 = arg1[0];
        }
        let ret;
        if (typeof arg2 === "undefined") {
            if (arg1.substring(0, 1) === ".") {
                arg1 = arg1.substring(1);
            }
            if (document.querySelectorAll) {
                ret = document.querySelectorAll("." + arg1);
            }
            if (document.getElementsByClassName) {
                ret = document.getElementsByClassName(arg1);
            }
        } else if (arg1.querySelectorAll) {
            if (arg2.substring(0, 1) !== ".") {
                arg2 = "." + arg2;
            }
            ret = arg1.querySelectorAll(arg2);
        }
        var arr = [];
        for (let i = 0; i < ret.length; i++) {
            arr.push(ret[i]);
        }
        return arr;
    },
    /***
     * 获取元素element的父元素
     * ***/
    parent: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        return element.parentNode;
    },
    /***
     * 获取element的子元素，arg:元素名称 / className / id / true获取包含文本元素的所有子元素
     * ****/
    children: function (arg) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let _type = typeof arg;
        if (_type === 'boolean' && arg) {
            return element.childNodes;
        }
        var result = [], i, child;
        if (_isString(arg)) {
            let firstChar = arg.substring(0, 1);
            let tagName = arg.toLowerCase();
            if (firstChar === "#") {
                let r = DomApiObj.getChildrenById.call(element, arg);
                return r;
            }
            if (firstChar === ".") {
                return DomApiObj.getChildrenByClass.call(element, arg);
            }
            for (i = 0; i < element.childNodes.length; i++) {
                child = element.childNodes[i];
                if (child.nodeName.toLowerCase() === tagName) {
                    result.push(child);
                }
            }

            return result;
        }
        for (i = 0; i < element.childNodes.length; ++i) {
            child = element.childNodes[i];
            if (child.nodeType === 1) {
                result.push(child);
            }
        }
        return result;
    },
    /***
     * 根据className 获取element的子元素
     * ****/
    getChildrenByClass: function (clazz) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var ret = [];
        var childs = element.children;
        for (var i = 0; i < childs.length; i++) {
            if (DomApiObj.hasClass.call(childs[i], clazz)) {
                ret.push(childs[i]);
            }
        }
        return ret;
    },
    /***
     * 根据id获取element元素的子元素
     * ***/
    getChildrenById: function (id) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var childs = element.children;
        if (id.indexOf("#") === 0) {
            id = id.substring(1);
        }
        for (var i = 0; i < childs.length; i++) {
            if (id === DomApiObj.attribute.call(childs[i], "id")) {
                return childs[i];
            }
        }
        return undefined;
    },
    /**
     * 根据标签名称获取element的子元素
     * ****/
    getChildrenByName: function (name) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var ret = [];
        var childs = element.children;
        var isArr = _isArray(name);
        for (var i = 0; i < childs.length; i++) {
            if (isArr) {
                if (_isInArray(childs[i].nodeName, name)) {
                    ret.push(childs[i]);
                }
            } else {
                if (childs[i].nodeName === name) {
                    ret.push(childs[i]);
                }
            }
        }
        return ret;
    },
    /***
     * 获取所有相邻节点
     * canTextNode是否包括文本节点,或者是class类名
     * *****/
    siblings: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }        
        var nextAll = DomApiObj.nextAll.call(element, canTextNode);
        var preAll = DomApiObj.previousAll.call(element, canTextNode);
        preAll.push.apply(preAll, nextAll);
        return preAll;
    },
    forSiblings:function(fn){
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }  
        let prev = element.previousSibling;  
        while(prev ){
            if(prev.nodeType === 1){
               let r = fn(prev);
               if(r !== undefined && !r){
                    break;
               }
            }
            prev = prev.previousSibling;
        }   
        let next = element.nextSibling;  
        while(next ){
            if(next.nodeType === 1){               
                let r = fn(next);
               if(r !== undefined && !r){
                    break;
               }
            }
            next = next.nextSibling;
        }  
    },
    /**
     * 获取元素的下一个同级元素，
     * canTextNode：是否包括文本节点
     * ****/
    next: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var result = element.nextSibling;
        if (!result) {
            return;
        }
        if (canTextNode) {
            return result;
        }
        if (result.nodeType !== 1) {
            return DomApiObj.next.call(result);
        }
        return result;
    },
    /***
     * 获取element元素后面的所有同级元素
     * canTextNode：是否包括文本节点,或者是class类名
     * ***/
    nextAll: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let clz = (typeof canTextNode === "string" && canTextNode.indexOf(".")) === 0 ? canTextNode : undefined;
        if(clz){
            canTextNode = false;
        }
        var ret = [];
        var nextEle = DomApiObj.next.call(element, canTextNode);
        while (nextEle) {
            if(clz){
                if(DomApiObj.hasClass.call(nextEle,clz)){
                    ret.push(nextEle);
                }              
            }else{
                ret.push(nextEle);
            }            
            nextEle = DomApiObj.next.call(nextEle, canTextNode);
        }
        return ret;
    },
    /***
     * 获取element元素的前一个同级元素
     * canTextNode：是否包括文本节点
     * ***/
    previous: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var result = element.previousSibling;
        if (!result) {
            return;
        }
        if (canTextNode) {
            return result;
        }
        if (result.nodeType !== 1) {
            return DomApiObj.previous.call(result);
        }
        return result;
    },
    /***
     * 获取element元素的前所有的同级元素
     * canTextNode：是否包括文本节点,或者是class类名
     * ***/
    previousAll: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let clz = (typeof canTextNode === "string" && canTextNode.indexOf(".")) === 0 ? canTextNode : undefined;
        if(clz){
            canTextNode = false;
        }
        var ret = [];
        var preEle = DomApiObj.previous.call(element, canTextNode);
        while (preEle) {
            if(clz){
                if(DomApiObj.hasClass.call(preEle,clz)){
                    ret.unshift(preEle);
                }                
            }else{
                ret.unshift(preEle);
            } 
            preEle = DomApiObj.previous.call(preEle, canTextNode);
        }
        return ret;
    },
    /****
     * 设置/获取element的属性,获取属性:attribute=string/[s1,s2]
     * 设置属性attribute={}
     * ****/
    attribute: function (attribute) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isLiteralObject(attribute)) { //多个元素同时设置属性
            _each(element, function (e) {
                DomApiObj.attribute.call(e, attribute);
            });
            return this;
        }
        if (isArr) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var result, i, keys;
        //获取一个属性
        if (typeof attribute === "string") {
            if (attribute === 'class' && element['className'] !== undefined) {//class
                result = element.className;
            } else if (attribute === 'for' && element['htmlFor'] !== undefined) {//for
                result = element.htmlFor;
            } else if (attribute === 'value' && element['value'] !== undefined) {//value?               
                return element.value;
            } else {
                if(attribute === "checked"){
                    result =   element.checked;
                }else{
                    result = element.getAttribute(attribute);
                }
            }            
            if (result === null) {
                result = undefined;
            }
            return result;
        }
        //获取多个
        if (_isArray(attribute)) {
            keys = Object.keys(attribute);
            for (i = 0; i < keys.length; ++i) {
                result[attribute[keys[i]]] = DomApiObj.attribute.call(element, attribute[keys[i]]);
            }
            return result;
        }
        //设置属性
        if (_isLiteralObject(attribute)) {
            keys = Object.keys(attribute);
            for (i = 0; i < keys.length; ++i) {
                if (attribute[keys[i]] === null || attribute[keys[i]] === undefined) {
                    element.removeAttribute(keys[i]);
                    if(keys[i] === "checked"){
                        element.checked = false;
                    }
                    if(keys[i] === "selected"){
                        element.selected = false;
                    }
                } else {                   
                    if(keys[i] === "checked"){
                        element.checked = attribute[keys[i]];
                    }else if(keys[i] === "selected"){
                        element.selected = attribute[keys[i]];
                    }else{
                        element.setAttribute(keys[i], attribute[keys[i]]);
                    }
                }
            }
            return this;
        }
    },
    /***
     * 获取或者设置元素element的宽度
     * ***/
    width: function (width) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "width", width);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /***
     * 获取或者设置元素element的高度
     * ***/
    height: function (height) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "height", height);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的内宽度
     * ***/
    innerWidth: function (width) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "width", width, "inner");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的内高度
     * ***/
    innerHeight: function (height) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "height", height, "inner");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的外宽度
     * ***/
    outerWidth: function (width) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "width", width, "outer");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的外高度
     * ***/
    outerHeight: function (height) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "height", height, "outer");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /****
     * 设置/获取element元素的scrollLeft
     * *****/
    scrollLeft: function (left) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = _getSetScroll(element, "scrollLeft", left);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /****
     * 设置/获取element元素的scrollTop
     * *****/
    scrollTop: function (top) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = _getSetScroll(element, "scrollTop", top);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /***
     * 设置/获取element元素的position
     * *****/
    position: function (pos) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (pos) {//设置位置
            DomApiObj.css.call(element, pos);
            return this;
        } else {//获取位置属性
            if (Array.isArray(element)) {
                element = element[0];
            }
            var offsetParent, offset,
                parentOffset = { top: 0, left: 0 };
            if (!DomApiObj.inDom.call(element)) {
                return parentOffset;
            }
            if (DomApiObj.css.call(element, "position") === "fixed") {
                offset = element.getBoundingClientRect();
            } else {
                offsetParent = DomApiObj.getOffsetParent.call(element);
                offset = DomApiObj.offset.call(element);
                if (offsetParent.nodeName.toLowerCase() !== "html") {
                    parentOffset = DomApiObj.offset.call(offsetParent);
                }
                parentOffset.top += DomApiObj.css.call(offsetParent, "borderTopWidth");
                parentOffset.left += DomApiObj.css.call(offsetParent, "borderLeftWidth");
            }
            return {
                top: offset.top - parentOffset.top - DomApiObj.css.call(element, "marginTop"),
                left: offset.left - parentOffset.left - DomApiObj.css.call(element, "marginLeft")
            };
        }
    },
    /***
     * 元素是否脱离了文档
     * ***/
    inDom() {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let r = window.document.contains(element);
        if(!r){
            let prt = element.parentNode;
            while(prt){
                if(prt.nodeName === "BODY"){                  
                    r = true;
                    break;
                }
                prt = prt.parentNode;
            }
        }
        return r;
    },
    /***
     * 获取element元素相对位置的参考父元素
     * ****/
    getOffsetParent() {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var offsetParent = element.offsetParent;
        while (offsetParent && offsetParent.nodeName.toLowerCase() !== "html" && DomApiObj.css.call(offsetParent, "position") === "static") {
            offsetParent = offsetParent.offsetParent;
        }
        return offsetParent || document.documentElement;
    },
    /***
     * 获取element的相对视窗的偏移量数据
     * ****/
    offset: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var ofs = {
            top: 0,
            left: 0
        };
        if (!DomApiObj.inDom.call(element)) {
            return ofs;
        }
        if (element.getBoundingClientRect) {
            let box = element.getBoundingClientRect();
            ofs.top = box.top;
            ofs.left = box.left;
        }
        let docElem = element.ownerDocument.documentElement;
        let ret = {
            top: ofs.top + (window.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
            left: ofs.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
        };
        return ret;
    },
    /****
     * 设置/获取元素的css样式，获取时候style参数必须是字符串的css名称
     * ****/
    css: function (style) {       
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isLiteralObject(style)) { //多个元素一起设置样式
            _each(element, function (e) {
                DomApiObj.css.call(e, style);
            });
            return this;
        }
        if (isArr) { //是数组
            if(element.length === 0){
                return;
            }
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        if (typeof style === "string") {
            return _getComputedStyle(element, cssNameProperty(style));
        }
        var keys, i;
        if (_isArray(style)) {
            var css = {};
            keys = Object.keys(style);
            for (i = 0; i < keys.length; ++i) {
                css[style[keys[i]]] = _getComputedStyle(element, cssNameProperty(style[keys[i]]));
            }
            return css;
        }
        if (_isLiteralObject(style)) {
            keys = Object.keys(style);
            for (i = 0; i < keys.length; ++i) {
                let cName = cssNameProperty(keys[i]);
                let value = style[keys[i]] + "";                              
                if (value.indexOf("#") < 0 && value.indexOf("%") < 0 && /^-?\d+\.?\d*$/.test(value) && !CSSNumber[cName]) {
                    value = value + "px";
                }
                if(cName === "backgroundColor" && value === "none"){
                    value = "transparent";
                }
                element.style[cName] = value;
            }
            return this;
        }
    },
    /***
     * 获取元素element的class
     * ***/
    getClass: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var attribute = DomApiObj.attribute.call(element, 'class');
        if (!attribute) {
            return [];
        }
        attribute = attribute.split(' ');
        var classNames = [], keys, i;
        keys = Object.keys(attribute);
        for (i = 0; i < keys.length; ++i) {
            if (attribute[keys[i]] === '') {
                continue;
            }
            classNames.push(attribute[keys[i]]);
        }
        return classNames;
    },
    /***
     * element元素是否存在className，className可以是数组
     * ****/
    hasClass: function (className) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        if (_isString(className)) {
            if (className.indexOf(".") === 0) {
                className = className.substring(1);
            }
            return _indexOf(DomApiObj.getClass.call(element), className) > -1 ? true : false;
        } else if (_isArray(className)) {
            var elementClasses = DomApiObj.getClass.call(element);
            for (var i = 0; i < className.length; i++) {
                if (_indexOf(className[i], elementClasses) === -1) {
                    return false;
                }
            }
            return true;
        } else {
            return false;
        }
    },
    /****
     * element元素添加class
     * ****/
    addClass: function (className) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isIterable(element)) {
            _each(element, function (e) {
                DomApiObj.addClass.call(e, className);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        if (_isArray(className)) {
            var i, keys = Object.keys(className);
            for (i = 0; i < keys.length; i++) {
                DomApiObj.addClass.call(element, className[keys[i]]);
            }
            return DomUtils;
        }
        var classes = DomApiObj.getClass.call(element);
        if (_indexOf(classes, className) === -1) {
            classes.push(className);
        }
        classes = classes.join(' ');
        DomApiObj.attribute.call(element, { class: classes });
        return this;
    },
    /*****
     * 移除元素的class
     * ******/
    removeClass: function (className) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isIterable(element)) {
            _each(element, function (e) {
                DomApiObj.removeClass.call(e, className);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.removeClass" + element + " is not a DOMNode object");
        }
        if (!className) {
            return DomApiObj.attribute.call(element, { class: "" });
        }     
        var classes = DomApiObj.getClass.call(element);
        var arr = className.split(/\s+/);
        for (let i = 0; i < arr.length; i++) {
            let j = _indexOf(classes, arr[i]);
            if (j !== -1) {
                classes.splice(j, 1);
            }
        }
        DomApiObj.attribute.call(element, { class: classes.join(' ') });
        return this;
    },
    /***
     * 复制元素
     * isDeep是否深复制，复制数据及事件
     * ****/
    copy: function (isDeep) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.copy" + element + " is not a DOMNode object");
        }
        var newEl = element.cloneNode(true);
        if (isDeep) {
            var events = element.events;
            if (events) {
                newEl.events = events;//复用复制的事件
                let namekeys = Object.keys[events];
                for (let i = 0; i < namekeys.length; i++) {
                    let eventName = namekeys[i];
                    if (newEl.addEventListener) {
                        newEl.addEventListener(eventName, commHandleEvent, false);
                    } else {
                        newEl["on" + eventName] = commHandleEvent;
                    }
                }
            }
            var _eldata = element._eldata;
            if (_eldata) {
                newEl._eldata = _eldata;
            }
        }
        return newEl;
    },
    /**
     * 往元素设置/读取html内容
     * ***/
    html: function (string) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isString(string)) {
            _each(element, function (e) {
                DomApiObj.html.call(e, string);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.html" + element + " is not a DOMNode object");
        }
        if (_isString(string)) {
            element.innerHTML = string;
            return this;
        }
        element = _getArrayFirstEl(element);
        return element.innerHTML;
    },
    /**
     * 往元素设置/读取innertText
     * ***/
    text: function (string) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isString(string)) {
            _each(element, function (e) {
                DomApiObj.text.call(e, string);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.text " + element + " is not a DOMNode object");
        }
        if (_isString(string)) {
            if (element.innerText) {
                element.innerText = string;
            } else {
                element.textContent = string;
            }
            return this;
        }
        element = _getArrayFirstEl(element);
        if (element.innerText) {
            return element.innerText;
        }
        return element.textContent;
    },
    /***
     * 设置或者获取元素的value值
     * ***/
    value: function (value) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var hooks, ret;
        if (typeof value === "undefined") {//获取值
            hooks = valHooks[element.nodeName.toLowerCase()];
            if (hooks && hooks.get) {
                return hooks.get(element);
            }
            ret = element.value;
            return typeof ret === "string" ? _trim(ret) : ret == null ? "" : ret;
        } else {//设置值
            hooks = valHooks[element.nodeName.toLowerCase()];
            if (hooks && hooks.set) {
                return hooks.set(element);
            }
            element.value = value;
        }
        return this;
    },
    /**
     * 判定元素是否处于隐藏状态
     * ***/
    isHide: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        return DomApiObj.css.call(element, "display") === "none";
    },
    /***
     * 显示元素
     * ***/
    show: function (animate) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.show.call(e);
            });
            return this;
        }
        if (animate && animate.length > 1) {
            let args = [];
            for (let i = 0; i < animate.length; i++) {
                args.push(animate[i]);
            }
            $B.show.apply(this, args);
        } else {
            element.style.display = "";
            if(  element.style.opacity === '0' || element.style.opacity === 0){
                element.style.opacity = 1;
            }
        }
        return this;
    },
    /**
     * 隐藏元素
     * ***/
    hide: function (animate) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.hide.call(e);
            });
            return this;
        }
        if (animate && animate.length > 1) {
            let args = [];
            for (let i = 0; i < animate.length; i++) {
                args.push(animate[i]);
            }
            $B.hide.apply(this, args);
        } else {
            //element.style.display = "";
            element.style.display = "none";
        }
        return this;
    },
    /**
     * 将html/元素添加到element元素内部的后面
     * ***/
    append: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'append', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.append " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.append.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }     
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.appendChild(html[i]);
            }
        }else{
            element.appendChild(html);
        }
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /**
     * 将html/元素添加到element元素内部的前面
     * ***/
    prepend: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'prepend', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.prepend " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.prepend.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.insertBefore(html[i], element.firstChild);
            }
        }else{
            element.insertBefore(html, element.firstChild);
        }        
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /***
     * 将html/元素插入到element后面
     * ***/
    after: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'after', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.after " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.after.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.parentNode.insertBefore(html[i], element.nextSibling);
            }
        }else{
            element.parentNode.insertBefore(html, element.nextSibling);
        }        
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /***
     * 将html/元素插入到element前面
     * ***/
    before: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'before', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.before " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.before.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.parentNode.insertBefore(html[i], element);
            }
        }else{
            element.parentNode.insertBefore(html, element);
        }        
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /***
     * 将html/元素替换element前面
     * ***/
    replace: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'replace', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.replace " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.replace.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        DomApiObj.clearElement.call(element);
        element.parentNode.replaceChild(html, element);
        return html;
    },
    /**
     * 清理element的数据和事件
     * **/
    clearElement: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (forachExecute(element, "clearElement")) {
            return this;
        }
        element._eldata = undefined;
        var events = element.events;
        if (events) {
            element.events = undefined;
            var eventKeys = Object.keys(events);
            for (let i = 0; i < eventKeys.length; i++) {
                let eventName = eventKeys[i];
                element.removeEventListener(eventName, commHandleEvent);//移除通用处理
                events[eventName] = undefined;
            }
        }
        return this;
    },
    /**
     * 移除element下所有子元素
     * 或者是某个class的子元素
     * **/
    removeChilds: function (args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (forachExecute(element, "removeChilds")) {
            return this;
        }
        var ret = [];
        for (let i = 0; i < element.childNodes.length; i++) {
            let child = element.childNodes[i];
            if (args ) {
                if ( child.nodeType === 1  && args.indexOf(".") === 0) { //按class
                    if (DomApiObj.hasClass.call(child, args.substring(1))) {
                        ret.push(child);
                    }
                }
            } else {
                ret.push(child);
            }
        }
        for (let i = 0; i < ret.length; i++) {
            let child = ret[i];
            DomApiObj.clearElement.call(child);
            element.removeChild(child);
        }
        return ret;
    },
    /**
     * 移除element元素,会将相关数据和事件移除
     * ***/
    remove: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (forachExecute(element, "remove")) {
            return;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.remove " + element + " is not a DOMNode object");
        }
        var parent = element.parentNode;
        DomApiObj.clearElement.call(element);
        if (parent) {
            return parent.removeChild(element);
        }
        return element;
    },
    /**
     * 移除element元素,并且还保留数据和事件移除
     * ***/
    detach: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        let exeRet = forachExecute(element, "detach");
        if (exeRet) {
            return exeRet;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.remove " + element + " is not a DOMNode object");
        }
        var parent = element.parentNode;
        if(parent){
            element._isRetainEvent = true; //跳过domRemove监听，不需要清除元素上的数据和事件   
            parent.removeChild(element);
            setTimeout(function () {
                element._isRetainEvent = undefined;
            }, 10);
        }       
        return element;
    },
    /***
     * 移除element下的所有元素（保留事件-数据），并将这些元素数组形式返回
     * ***/
    detachChilds: function (args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (Array.isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.remove " + element + " is not a DOMNode object");
        }
        var ret = [];
        while (element.childNodes.length > 0) {
            let child = element.childNodes[0];
            if (args) {
                if (args.indexOf(".") === 0) { //按class
                    if (!DomApiObj.hasClass.call(child, args.substring(1))) {
                        continue;
                    }
                }
            }
            DomApiObj.detach.call(child);
            if (!(child.nodeType === 3 && $B.replaceSpaceChar(child.nodeValue) === "")) {
                ret.push(child);
            }
        }
        return ret;
    },
    /***
     * 设置，读取简单类型的属性，属性数据会在标签上形成data-xxx属性
     * args:属性名称，或者{prop:value},移除数据用{name:undefined/null}
     * ***/
    propData: function (args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        var isSet = _isLiteralObject(args);
        if (isArr && isSet) {
            _each(element, function (e) {
                DomApiObj.propData.call(e, args);
            });
            return true;
        }
        if (isArr) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.data " + element + " is not a DOMNode object");
        }
        var i, dataset, attrs, keys, attr, l;
        //获取元素上的所有数据
        if (args === undefined) {
            if (element.hasOwnProperty('dataset')) {
                return element.dataset;
            } else {//通过属性获取
                dataset = {};
                for (i = 0, l = element.attributes.length; i < l; i++) {
                    attr = element.attributes.item(i);
                    if (attr.nodeName.substr(0, 5) !== 'data-') {
                        continue;
                    }
                    dataset[attr.nodeName.substr(5)] = attr.nodeValue;
                }
                return dataset;
            }
        }
        //获取一个属性
        if (_isString(args)) {
            return DomApiObj.attribute.call(element, 'data-' + args);
        }
        //获取多个数据
        if (_isArray(args)) {
            dataset = {};
            for (i = 0, l = args.length; i < l; i++) {
                dataset[args[i]] = DomApiObj.attribute.call(element, 'data-' + args[i]);
            }
            return dataset;
        }
        //设置数据{}
        if (isSet) {
            attrs = {};
            keys = Object.keys(args);
            for (i = 0; i < keys.length; ++i) {
                attrs['data-' + keys[i]] = args[keys[i]];
            }
            DomApiObj.attribute.call(element, attrs);
        }
        return this;
    },
    /***
     * 移除简单类型属性
     * key=属性名称
     * ****/
    removePropData: function (key) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.removePropData.call(e, key);
            });
            return;
        }
        key = "data-" + key;
        element.removeAttribute(key);
        return this;
    },
    removeAttribute: function (key) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.removeAttribute.call(e, key);
            });
            return;
        }
        element.removeAttribute(key);
        return this;
    },
    /**
     * 设置元素数据，key：数据key，dataObject数据对象
     * 该api会在element._eldata上生成数据对象
     * ***/
    setData: function (key, dataObject) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.setData.call(e, key, dataObject);
            });
            return true;
        }
        var cached = element._eldata;
        if (!cached) {
            cached = {};
            element._eldata = cached;
        }
        if (dataObject === undefined || dataObject === null) {
            delete cached[key];
        } else {
            cached[key] = dataObject;
        }
        return this;
    },
    /***
     * 根据key获取element元素的数据
     * ***/
    getData: function (key) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var cached = element._eldata;
        if (!cached) {
            return undefined;
        }
        return cached[key];
    }
};
DomUtils = {
    $: function (arg1, arg2) {
        let el = arg1;
        var obj = {
            _el: el
        };
        obj["__proto__"] = DomApiObj;
        return obj;
    },
    /***
     * 对元素添加一个事件监听
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * params:额外的参数
     * **/
    addListener: function (element, eventName, listener, params) {
        return DomApiObj.addListener.call(element, eventName, listener, params);
    },
    /***
     * 对元素移除事件
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * **/
    removeListener: function (element, eventName, listener) {
        return DomApiObj.removeListener.call(element, eventName, listener);
    },
    /***
     * 触发事件
     * ****/
    trigger: function (element, eventName, args) {
        return DomApiObj.trigger.call(element, eventName, args);
    },
    /***
     * 接触element元素的某一类事件
     * eventName=click、mousedown、mouseup 事件名称或者 namespace.eventName 或者 namespace.*
     * ***/
    offEvents: function (element, eventName) {
        return DomApiObj.offEvents.call(element, eventName);
    },
    /***
     * 绑定事件
     * ***/
    bind: function (element, arg1, arg2) {
        if (_isLiteralObject(arg1)) {
            return DomApiObj.bind.call(element, arg1);
        } else if (_isFunction(arg2)) {
            if (DomApiObj[arg1]) {
                return DomApiObj[arg1].call(element, arg2);
            }
        }
    },
    click: function (element, listener) {
        return DomApiObj.click.call(element, listener);
    },
    contextmenu: function (element, listener) {
        return DomApiObj.contextmenu.call(element, listener);
    },
    paste:function(element, listener){
        return DomApiObj.paste.call(element, listener);
    },
    dblclick: function (element, listener) {
        return DomApiObj.dblclick.call(element, listener);
    },
    mouseover: function (element, listener) {
        return DomApiObj.mouseover.call(element, listener);
    },
    mouseout: function (element, listener) {
        return DomApiObj.mouseout.call(element, listener);
    },
    mousedown: function (element, listener) {
        return DomApiObj.mousedown.call(element, listener);
    },
    mouseup: function (element, listener) {
        return DomApiObj.mouseup.call(element, listener);
    },
    mouseenter: function (element, listener) {
        return DomApiObj.mouseenter.call(element, listener);
    },
    mouseleave: function (element, listener) {
        return DomApiObj.mouseleave.call(element, listener);
    },
    mousemove: function (element, listener) {
        return DomApiObj.mousemove.call(element, listener);
    },
    touchstart: function (element, listener) {
        return DomApiObj.touchstart.call(element, listener);
    },
    touchend: function (element, listener) {
        return DomApiObj.touchend.call(element, listener);
    },
    touchmove: function (element, listener) {
        return DomApiObj.touchmove.call(element, listener);
    },
    touchcancel: function (element, listener) {
        return DomApiObj.touchcancel.call(element, listener);
    },
    focus: function (element, listener) {
        return DomApiObj.focus.call(element, listener);
    },
    blur: function (element, listener) {
        return DomApiObj.blur.call(element, listener);
    },
    select: function (element, listener) {
        return DomApiObj.select.call(element, listener);
    },
    change: function (element, listener) {
        return DomApiObj.change.call(element, listener);
    },
    submit: function (element, listener) {
        return DomApiObj.submit.call(element, listener);
    },
    reset: function (element, listener) {
        return DomApiObj.reset.call(element, listener);
    },
    onload: function (element, listener) {
        return DomApiObj.onload.call(element, listener);
    },
    scroll: function (element, listener) {
        return DomApiObj.scroll.call(element, listener);
    },
    unload: function (element, listener) {
        return DomApiObj.unload.call(element, listener);
    },
    resize: function (element, listener) {
        return DomApiObj.resize.call(element, listener);
    },
    keydown: function (element, listener) {
        return DomApiObj.keydown.call(element, listener);
    },
    keyup: function (element, listener) {
        return DomApiObj.keyup.call(element, listener);
    },
    keypress: function (element, listener) {
        return DomApiObj.keypress.call(element, listener);
    },
    input:function(element, listener){
        return DomApiObj.input.call(element, listener);
    },
    /**
     * 是否是dom元素
     * @param {object} element
     * @returns {boolean}
     */
    isElement: function (element) {
        return DomApiObj.isElement.call(element);
    },
    /**
     * 是否是 DOMNode
     * @param node
     * @returns {*}
     */
    isNode: function (node) {
        return DomApiObj.isNode.call(node);
    },
    /***
     * 获取元素element，位置、高宽信息
     * ***/
    domInfo: function (element) {
        return DomApiObj.domInfo.call(element);
    },
    /*****
     * selector api 返回数组
     * element：元素
     * selector：刷选条件
     * *****/
    findBySelector: function (element, selector) {
        return DomApiObj.findBySelector.call(element, selector);
    },
    /***
     * 根据id查找元素
     * arg1:id / dom元素
     * arg2:当arg1是dom时候，arg2为id
     * ***/
    findbyId: function (arg1, arg2) {
        if(!arg2){
            arg2 = arg1;
            arg1 = document;
        }
        return DomApiObj.findbyId.call(arg1, arg2);
    },
    /***
     * 根据tag Name查询元素
     * arg1:name / dom元素
     * arg2:当arg1是dom时候，arg2为name
     * ***/
    findByTagName: function (arg1, arg2) {
        return DomApiObj.findByTagName.call(arg1, arg2);
    },
    /***
     * 根据class查询元素
     * arg1：className / dom元素
     * arg2：当arg1是dom元素，arg2位className
     * ***/
    findByClass: function (arg1, arg2) {
        return DomApiObj.findByClass.call(arg1, arg2);
    },
    /***
     * 获取元素element的父元素
     * ***/
    parent: function (element) {
        return DomApiObj.parent.call(element);
    },
    /***
     * 获取element的子元素，arg:元素名称 / className / id / true获取包含文本元素的所有子元素
     * ****/
    children: function (element, arg) {
        return DomApiObj.children.call(element, arg);
    },
    /***
     * 根据className 获取element的子元素
     * ****/
    getChildrenByClass: function (element, clazz) {
        return DomApiObj.getChildrenByClass.call(element, clazz);
    },
    /***
     * 根据id获取element元素的子元素
     * ***/
    getChildrenById: function (element, id) {
        return DomApiObj.getChildrenById.call(element, id);
    },
    /**
     * 根据标签名称获取element的子元素
     * ****/
    getChildrenByName: function (element, name) {
        return DomApiObj.getChildrenByName.call(element, name);
    },
    siblings: function (element, canTextNode) {
        return DomApiObj.siblings.call(element, canTextNode);
    },
    forSiblings:function (element, fn) {
        return DomApiObj.forSiblings.call(element, fn);
    },
    /**
     * 获取元素的下一个同级元素，
     * canTextNode：是否包括文本节点
     * ****/
    next: function (element, canTextNode) {
        return DomApiObj.next.call(element, canTextNode);
    },
    /***
     * 获取element元素后面的所有同级元素
     * canTextNode：是否包括文本节点
     * ***/
    nextAll: function (element, canTextNode) {
        return DomApiObj.nextAll.call(element, canTextNode);
    },
    /***
     * 获取element元素的前一个同级元素
     * canTextNode：是否包括文本节点
     * ***/
    previous: function (element, canTextNode) {
        return DomApiObj.previous.call(element, canTextNode);
    },
    /***
     * 获取element元素的前所有的同级元素
     * canTextNode：是否包括文本节点
     * ***/
    previousAll: function (element, canTextNode) {
        return DomApiObj.previousAll.call(element, canTextNode);
    },
    /***
     * 获取或者设置元素element的宽度
     * ***/
    width: function (element, width) {
        return DomApiObj.width.call(element, width);
    },
    /***
     * 获取或者设置元素element的高度
     * ***/
    height: function (element, height) {
        return DomApiObj.height.call(element, height);
    },
    /**
     * 获取或者设置元素element的内宽度
     * ***/
    innerWidth: function (element, width) {
        return DomApiObj.innerWidth.call(element, width);
    },
    /**
     * 获取或者设置元素element的内高度
     * ***/
    innerHeight: function (element, height) {
        return DomApiObj.innerHeight.call(element, height);
    },
    /**
     * 获取外部width/height
     * **/
    outerSize: function (element) {
        var w = DomApiObj.outerWidth.call(element);
        var h = DomApiObj.outerHeight.call(element);
        return {
            width: w,
            height: h
        };
    },
    /**
     * 获取或者设置元素element的外宽度
     * ***/
    outerWidth: function (element, width) {
        return DomApiObj.outerWidth.call(element, width);
    },
    /**
     * 获取或者设置元素element的外高度
     * ***/
    outerHeight: function (element, height) {
        return DomApiObj.outerHeight.call(element, height);
    },
    /****
     * 设置/获取element元素的scrollLeft
     * *****/
    scrollLeft: function (element, left) {
        return DomApiObj.scrollLeft.call(element, left);
    },
    /****
     * 设置/获取element元素的scrollTop
     * *****/
    scrollTop: function (element, top) {
        return DomApiObj.scrollTop.call(element, top);
    },
    /***
     * 设置/获取element元素的position
     * *****/
    position: function (element, pos) {
        return DomApiObj.position.call(element, pos);
    },
    /***
     * 元素是否脱离了文档
     * ***/
    inDom(element) {
        return DomApiObj.inDom.call(element);
    },
    /***
     * 获取element元素相对位置的参考父元素
     * ****/
    getOffsetParent(element) {
        return DomApiObj.getOffsetParent.call(element);
    },
    /***
     * 获取element的相对视窗的偏移量数据
     * ****/
    offset: function (element) {
        return DomApiObj.offset.call(element);
    },
    /****
     * 设置/获取元素的css样式，获取时候style参数必须是字符串的css名称
     * ****/
    css: function (element, style) {
        return DomApiObj.css.call(element, style);
    },
    /***
     * 获取元素element的class
     * ***/
    getClass: function (element) {
        return DomApiObj.getClass.call(element);
    },
    /***
     * element元素是否存在className，className可以是数组
     * ****/
    hasClass: function (element, className) {
        return DomApiObj.hasClass.call(element, className);
    },
    /****
     * element元素添加class
     * ****/
    addClass: function (element, className) {
        return DomApiObj.addClass.call(element, className);
    },
    /*****
     * 移除元素的class
     * ******/
    removeClass: function (element, className) {
        return DomApiObj.removeClass.call(element, className);
    },
    /***
     * 复制元素
     * isDeep是否深复制，复制数据及事件
     * ****/
    copy: function (element, isDeep) {
        return DomApiObj.copy.call(element, isDeep);
    },
    /**
     * 往元素设置/读取html内容
     * ***/
    html: function (element, string) {
        return DomApiObj.html.call(element, string);
    },
    /**
     * 往元素设置/读取innertText
     * ***/
    text: function (element, string) {
        return DomApiObj.text.call(element, string);
    },
    /***
     * 设置或者获取元素的value值
     * ***/
    value: function (element, value) {
        return DomApiObj.value.call(element, value);
    },
    /**
     * 判定元素是否处于隐藏状态
     * ***/
    isHide: function (element) {
        return DomApiObj.isHide.call(element);
    },
    /***
     * 显示元素
     * ***/
    show: function (element, args) {
        return DomApiObj.show.call(element, arguments);
    },
    /**
     * 隐藏元素
     * ***/
    hide: function (element, args) {
        return DomApiObj.hide.call(element, arguments);
    },
    /**
     * 将html/元素添加到element元素内部的后面
     * ***/
    append: function (element, html) {
        return DomApiObj.append.call(element, html);
    },
    /**
     * 将html/元素添加到element元素内部的前面
     * ***/
    prepend: function (element, html) {
        return DomApiObj.prepend.call(element, html);
    },
    /***
     * 将html/元素插入到element后面
     * ***/
    after: function (element, html) {
        return DomApiObj.after.call(element, html);
    },
    /***
     * 将html/元素插入到element前面
     * ***/
    before: function (element, html) {
        return DomApiObj.before.call(element, html);
    },
    /***
     * 将html/元素替换element
     * ***/
    replace: function (element, html) {
        return DomApiObj.replace.call(element, html);
    },
    /**
     * 清理element的数据和事件
     * **/
    clearElement: function (element) {
        if (!element || element.length === 0) {
            return;
        }
        return DomApiObj.clearElement.call(element);
    },
    /**
     * 移除element下所有子元素
     * **/
    removeChilds: function (element, clazz) {
        if (!element || element.length === 0) {
            return;
        }
        return DomApiObj.removeChilds.call(element, clazz);
    },
    /**
     * 移除element元素,会将相关数据和事件移除
     * ***/
    remove: function (element) {
        if (!element || element.length === 0) {
            return;
        }
        return DomApiObj.remove.call(element);
    },
    /**
     * 移除element元素,并且还保留数据和事件移除
     * ***/
    detach: function (element) {
        return DomApiObj.detach.call(element);
    },
    /***
     * 移除element下的所有元素（保留事件-数据），并将这些元素数组形式返回
     * ***/
    detachChilds: function (element, args) {
        return DomApiObj.detachChilds.call(element, args);
    },
    /***
     * 设置，读取简单类型的属性，属性数据会在标签上形成data-xxx属性
     * args:属性名称，或者{prop:value},移除数据用{name:undefined/null}
     * ***/
    propData: function (element, args) {
        return DomApiObj.propData.call(element, args);
    },
    /***
     * 移除简单类型属性
     * key=属性名称
     * ****/
    removePropData: function (element, key) {
        return DomApiObj.removePropData.call(element, key);
    },
    removeAttribute: function (element, key) {
        return DomApiObj.removeAttribute.call(element, key);
    },
    removeAttr:function(element, key){
        return DomApiObj.removeAttribute.call(element, key);
    },
    attribute: function (element, args) {
        return DomApiObj.attribute.call(element, args);
    },
    attr:function(element, args){
        return DomApiObj.attribute.call(element, args);
    },
    removeData: function (element, key) {
        return DomApiObj.setData.call(element, key);
    },
    /**
     * 设置元素数据，key：数据key，dataObject数据对象
     * 该api会在element._eldata上生成数据对象
     * ***/
    setData: function (element, key, dataObject) {
        return DomApiObj.setData.call(element, key, dataObject);
    },
    /***
     * 根据key获取element元素的数据
     * ***/
    getData: function (element, key) {
        return DomApiObj.getData.call(element, key);
    },
    /***
     * 根据html创建元素，这个api需要进一步验证
     * *****/
    createEl: function (html) {
        var parent;
        if (/^<td/.test(html) || /^<th/.test(html)) {
            parent = document.createElement("tr");
        } else if (/^<tr/.test(html)) {
            parent = document.createElement("tbody");
        } else if (/^<tbody/.test(html) || /^<thead/.test(html) || /^<caption/.test(html) || /^<tfoot/.test(html)) {
            parent = document.createElement("table");
        } else if ((/^<dt/.test(html) || /^<dd/.test(html))) {
            parent = document.createElement("dl");
        } else if (/^<li/.test(html)) {
            parent = document.createElement("ul");
        } else {
            parent = document.createElement('div'); //创建一个空的div  
        }
        this.html(parent, html);
        var resNodes = parent.childNodes;
        var res = [];
        for (let i = 0; i < resNodes.length; i++) {
            let node = resNodes[i];
            res.push(node);
            parent.removeChild(node);
        }
        if (res.length === 1) {
            return res[0];
        }
        return res;
    },
    requestAnimationFrame: function () {
        return requestAnimationFrame;
    },
    cancelAnimationFrame: function () {
        return cancelAnimationFrame;
    },
    /**
     * 获取可视窗口的大小
     * ***/
    getViewSize: function () {
        if (document.compatMode === "BackCompat") {
            return {
                width: document.body.clientWidth,
                height: document.body.clientHeight
            };
        } else {
            return {
                width: document.documentElement.clientWidth,
                height: document.documentElement.clientHeight
            };
        }
    },
    /**
     * 获取页面包括滚动条的大小
     * ***/
    getPageSize: function () {
        if (document.compatMode === "BackCompat") {
            return {
                width: Math.max(document.body.scrollWidth,
                    document.body.clientWidth),
                height: Math.max(document.body.scrollHeight,
                    document.body.clientHeight)
            };
        } else {
            return {
                width: Math.max(document.documentElement.scrollWidth,
                    document.documentElement.clientWidth),
                height: Math.max(document.documentElement.scrollHeight,
                    document.documentElement.clientHeight)
            };
        }
    },
    /*****
     * 设置dom loaded后的回调函数
     * *****/
    onDomLoaded: function (handler) {
        if (_isDomLoaded !== false) {
            handler.call(null, _isDomLoaded);
            return DomUtils;
        }
        _domLoadedHandlers.push(handler);
        return DomUtils;
    },
    /*****
     * 设置dom ready后的回调函数
     * *****/
    onDomReady: function (handler) {
        if (_isDomReady !== false) {
            handler.call(null, _isDomReady);
            return DomUtils;
        }
        _domReadyHandlers.push(handler);
        return DomUtils;
    },
    /***
     * 设置dom元素删除、新增的监听
     * handler = function(element,flag){}
     * element相关联的元素，flag=0表示删除，1表示新增
     ****/
    onDomNodeChanged: function (handler) {
        if (!this._domChangedListner) {
            this._domChangedListner = [];
        }
        handler.errorcout = 0;
        this._domChangedListner.push(handler);
    },
    /***
     * 解除dom变化监听
     * ***/
    offDomNodeChanged: function (handler) {
        if (this._domChangedListner) {
            var newEvents = [];
            for (let i = 0; i < this._domChangedListner.length; i++) {
                if (handler !== this._domChangedListner[i]) {
                    newEvents.push(this._domChangedListner[i]);
                }
            }
            this._domChangedListner = newEvents;
        }
    },
    invokeDomChangedEvents: function (element, flag) {
        if (this._domChangedListner) {
            var newEvents = [];
            for (let i = 0; i < this._domChangedListner.length; i++) {
                let fn = this._domChangedListner[i];
                try {
                    let ret = fn(element, flag);
                    if (typeof ret !== 'undefined' && !ret) {
                        fn.errorcout = 5;//清理这个回调
                    } else {
                        fn.errorcout = 0;
                    }
                } catch (x) {
                    fn.errorcout++;
                }
                if (fn.errorcout < 3) {
                    newEvents.push(fn);
                }
            }
            this._domChangedListner = newEvents;
        }
    }
};

function forachExecute(element, opr) {
    if (_isIterable(element)) {
        var retArr = [];
        _each(element, function (e) {
            let ret = DomUtils[opr](e);
            retArr.push(ret);
        });
        return retArr;
    }
    return undefined;
}

function _elementInsert(element, opr, html) {
    var isArr = _isIterable(element);
    if (isArr) {
        var res = [];
        _each(element, function (e) {
            res.push(DomUtils[opr](e, html));
        });
        return res.length === 1 ? res[0] : res;
    }
    return undefined;
}

function _getArrayFirstEl(element) {
    var isArr = _isIterable(element);
    if (isArr) {
        element = element[0];
    }
    return element;
}

/***
 * 读写scroll值
 * ***/
function _getSetScroll(element, prop, value) {
    var isArr = _isIterable(element);
    if (typeof value === "undefined") {
        if (isArr) {
            element = element[0];
        }
        if (element.tagName === "BODY" || element === document) {
            if (prop === "scrollTop") {
                return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
            }
            return document.documentElement.scrollLeft || window.pageXOffset || document.body.scrollLeft;
        }
        return element[prop];
    } else {
        if (isArr) {
            _each(element, function (e) {
                _getSetScroll(e, prop, value);
            });
        } else {
            element[prop] = value;
        }
    }
}

/******
 * 读写dom的高、宽
 * ********/
function getSetWH(element, attrName, val, exra) {
    if(!element || element.nodeType === 3){
        return typeof val === "undefined" ?  0 : DomUtils;
    }
    if (typeof val === "undefined") { //只有两个参数是读操作
        let v = DomUtils.domInfo(element)[attrName];
        let boxSize = DomUtils.css(element, "box-sizing");
        if (v !== 0 && exra) { //存在 exra则说明是 inner、outer
            if (attrName === "width") { /***innerWidth**/
                // if (boxSize === "content-box") {
                //     // let pl = DomUtils.css(element, "padding-left");
                //     // let pr = DomUtils.css(element, "padding-right");
                //     // v = v + pl + pr;                  
                // }
                if (exra === "outer" && boxSize !== "border-box") {//outerWidth：  border
                    let bl = DomUtils.css(element, "border-left-width");
                    let br = DomUtils.css(element, "border-right-width");
                    v = v + bl + br;
                }else if(exra === "inner"){
                    let isTd = element.nodeName === "TD";
                    let bl = DomUtils.css(element, "padding-left");
                    let br = DomUtils.css(element, "padding-right");
                    v = v - bl - br;
                    let l = $B.DomUtils.css(element, "border-right-width");
                    let r = $B.DomUtils.css(element, "border-left-width");
                    if(isTd){
                        l = l / 2;
                        r = r / 2;
                    }
                    v = v - l - r;
                }
            } else { //高度 
                //innerHeight               
                if (exra === "outer" && boxSize !== "border-box") {//outerHeight border
                    let bl = DomUtils.css(element, "border-top-width");
                    let br = DomUtils.css(element, "border-bottom-width");
                    v = v + bl + br;
                }else if(exra === "inner"){
                    let isTd = element.nodeName === "TD";
                    let t = $B.DomUtils.css(element, "border-top-width");
                    let b = $B.DomUtils.css(element, "border-bottom-width");
                    if(isTd){
                        t = t / 2;
                        b = b / 2;
                    }
                    v = v - t - b;
                    let bl = DomUtils.css(element, "padding-top");
                    let br = DomUtils.css(element, "padding-bottom");
                    v = v - bl - br;
                }
            }
        }
        return v;
    } else {//写操作
        if (_isNumeric(val)) {
            let strVal = val + "";
            if (/.+\d+$/.test(strVal)) {
                val = val + "px";
            }
        }
        let css = {};
        css[attrName] = val;
        DomUtils.css(element, css);
        return DomUtils;
    }
}
/***
 * DOMReady处理函数
 * ***/
function _onDOMReady(e) {
    DomUtils.body = DomUtils.findByTagName('body')[0];
    DomUtils.head = DomUtils.findByTagName('head')[0];
    var event = new EventArgs(e);
    _isDomReady = event;
    _each(_domReadyHandlers, function (fn) {
        fn.call(null, event);
    });
}
/**
 * DOMLoaded处理函数
 * ***/
function _onDOMLoaded(e) {
    var event = new EventArgs(e);
    _isDomLoaded = event;
    _each(_domLoadedHandlers, function (fn) {
        fn.call(null, event);
    });
}

//on load
if (window.onload !== null) {
    _domLoadedHandlers.push(window.onload);
}
window.onload = _onDOMLoaded;

//on ready
var readyFn;
if (addListener === 'addEventListener') {
    readyFn = function (e) {
        document[removeListener]('DOMContentLoaded', readyFn, false);//移除
        readyFn = undefined;
        _onDOMReady(e);
    };
    document[addListener]('DOMContentLoaded', readyFn, false);
} else {
    readyFn = function (e) {
        if (document.readyState === 'complete') {
            document[removeListener]('onreadystatechange', readyFn);//移除
            readyFn = undefined;
            _onDOMReady(e);
        }
    };
    document[addListener]('onreadystatechange', readyFn);
}
//创建dom变化监听，用于触发事件清理逻辑
function clearElementEvents(el) {
    if (el.nodeType === 1) {
        if (el.events) {
           
            DomUtils.offEvents(el);
        }
        if(el._clearAllFn){
            el._clearAllFn();
        }
        let _droplistid = $B.DomUtils.attribute(el, "_droplistid");
        if (_droplistid) { //移除对应的下拉dom           
            setTimeout(function () {
                let ele = document.getElementById(_droplistid);
                if (ele) {
                    if(ele._clearAllFn){
                        ele._clearAllFn();
                    }
                    $B.DomUtils.remove(ele);
                }
            }, 1);
        }
        var children = el.children;
        if (children) {
            for (let i = 0; i < children.length; i++) {
                clearElementEvents(children[i]);
            }
        }
    }

}

var onNodeRemovedFn = function (event) {
    event = event._e;
    if (event.target.nodeType === 1) {
        DomUtils.invokeDomChangedEvents(event.target, 0);
        if (event.target._isRetainEvent) { //避免被多次触发的场景           
            return;
        }
        event.target._isRetainEvent = true;
        var children = event.target.children;
        if (children) {
            let childs = Array.from(children);            
            _onNodeRemoveEventTimer = setTimeout(() => {
                for (let i = 0; i < childs.length; i++) {
                    clearElementEvents(childs[i]);
                }
            }, 8);
        }
        clearElementEvents(event.target);
        setTimeout(function () {
            event.target._isRetainEvent = undefined;
        }, 9);
    }
};
DomUtils.addListener(document, "DOMNodeRemoved", onNodeRemovedFn);
var DOMNodeInsertedFn = function (event) {
    DomUtils.invokeDomChangedEvents(event.target, 1);
};
DomUtils.addListener(document, "DOMNodeInserted", DOMNodeInsertedFn);
$B.DomUtils = DomUtils;
$B.Dom = DomUtils;
$B.onLoad = $B.DomUtils.onDomLoaded;

/*******动画*******/
function _isVelocityEl() {
    if (!window["Velocity"]) {
        return;
    }
    return window["Velocity"];
}
$B.createEl = function(html){
   return DomUtils.createEl(html);
}; 
/** Velocity 动画配置项的默认值 
 * props = {   
    duration: 400,         // 动画执行时间
    easing: "swing",       // 缓动效果
    queue: "",             // 队列
    begin: undefined,      // 动画开始时的回调函数
    progress: undefined,   // 动画执行中的回调函数（该函数会随着动画执行被不断触发）
    complete: undefined,   // 动画结束时的回调函数
    display: undefined,    // 动画结束时设置元素的 css display 属性
    visibility: undefined, // 动画结束时设置元素的 css visibility 属性
    loop: false,           // 循环
    delay: false,          // 延迟
    mobileHA: true         // 移动端硬件加速（默认开启）
}
 * **/
$B.velocity = function (el, css, props) {
    var fn = _isVelocityEl();
    if (fn) {
        fn(el, css, props);
    }
};
$B.animate = $B.velocity;
function exeAnimate(animate, args) {
    var fn = _isVelocityEl();
    if (fn) {
        let duration = 500;
        let completeFn, elArr, el;
        for (let i = 0; i < args.length; i++) {
            if (i === 0) {
                el = args[0];
            } else if (_isFunction(args[i])) {
                completeFn = args[i];
            } else if (_isNumeric(args[i])) {
                duration = parseInt(args[i]);
            }
        }
        elArr = el;
        if (!_isArray(el)) {
            elArr = [];
            elArr.push(el);
        }

        var opt = { duration: duration };
        for (let i = 0; i < elArr.length; i++) {
            if (completeFn && i === elArr.length - 1) {
                opt["complete"] = completeFn;
            }
            let display = undefined;
            if (animate === "slideDown" || animate === "show" || animate === "fadeIn") { //显示
                if (elArr[i]["_display"] && elArr[i]["_display"] !== "none") {
                    display = elArr[i]["_display"];
                } else {
                    let tagName = elArr[i].tagName;
                    if (tagName === "TABLE") {
                        display = "table";
                    } else if (tagName === "TBODY") {
                        display = "table-row-group";
                    } else if (tagName === "THEAD") {
                        display = "table-header-group";
                    } else if (tagName === "TFOOT") {
                        display = "table-footer-group";
                    } else if (tagName === "TR") {
                        display = "table-row";
                    } else if (tagName === "TD") {
                        display = "table-cell";
                    } else {
                        display = undefined;
                    }
                }
            } else { //隐藏记录display
                let srcdisplay = $B.DomUtils.css(elArr[i], "display");
                elArr[i]["_display"] = srcdisplay;
            }
            opt.display = display;
            fn(elArr[i], animate, opt);
        }
    }
}
$B.slideUp = function () {
    exeAnimate("slideUp", arguments);
};
$B.slideDown = function () {
    exeAnimate("slideDown", arguments);
};
$B.toggle = function(){
    let el = arguments[0];
    if(!el.style || el.style.display !== "none"){
        exeAnimate("slideUp", arguments);
    }else{
        exeAnimate("slideDown", arguments);
    }
};
$B.hide = function () {
    exeAnimate("fadeOut", arguments);
};
$B.show = function () {
    exeAnimate("fadeIn", arguments);
};
$B.fadeIn = function () {
    exeAnimate("fadeIn", arguments);
};
$B.fadeOut = function () {
    exeAnimate("fadeOut", arguments);
};

(function ($) {
    var
        document = window.document,
        key,
        name,
        rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
        scriptTypeRE = /^(?:text|application)\/javascript/i,
        xmlTypeRE = /^(?:text|application)\/xml/i,
        jsonType = 'application/json',
        htmlType = 'text/html',
        blankRE = /^\s*$/,
        escape = encodeURIComponent,
        originAnchor = document.createElement('a');

    originAnchor.href = window.location.href;

    // Empty function, used as default callback
    function emptyFn() { }

    var ajaxSettings = {
        // Default type of request
        type: 'GET',
        // Callback that is executed before request
        beforeSend: emptyFn,//fn(data, type)
        // Callback that is executed if the request succeeds
        success: emptyFn, //fn(data, status, xhr)
        // Callback that is executed the the server drops error
        error: emptyFn,//fn(xhr, type, error)
        // Callback that is executed on request complete (both: error and success)
        complete: emptyFn,//fn(type, xhr, settings)
        // Transport
        xhr: function () {
            return new window.XMLHttpRequest();
        },
        // MIME types mapping
        // IIS returns Javascript as "application/x-javascript"
        accepts: {
            script: 'text/javascript, application/javascript, application/x-javascript',
            json: jsonType,
            xml: 'application/xml, text/xml',
            html: htmlType,
            text: 'text/plain'
        },
        // Whether the request is to another domain
        crossDomain: false,
        // Default timeout
        timeout: 0,
        onErrorEval:false,
        // Whether data should be serialized to string
        processData: true,
        // Whether the browser should be allowed to cache GET responses
        cache: true,
        //Used to handle the raw response data of XMLHttpRequest.
        //This is a pre-filtering function to sanitize the response.
        //The sanitized response should be returned
        dataFilter: emptyFn
    };

    // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
    function ajaxBeforeSend(xhr, settings) {
        if (settings.beforeSend(xhr, settings) === false) {
            return false;
        }
        //triggerGlobal(settings, context, 'ajaxSend', [xhr, settings]);
    }
    function ajaxSuccess(data, xhr, settings) {
        var status = 'success';
        settings.success(data, status, xhr);
        settings.complete(status, xhr, settings);
    }
    // type: "timeout", "error", "abort", "parsererror"
    function ajaxError(error, type, xhr, settings) {
        settings.error(xhr, type, error);
        settings.complete(type, xhr, settings);
    }

    function ajaxDataFilter(data, type, settings) {
        if (settings.dataFilter === emptyFn) {
            return data;
        }
        return settings.dataFilter(data, type);
    }

    function mimeToDataType(mime) {
        if (mime) {
            mime = mime.split(';', 2)[0];
        }
        return mime && (mime === htmlType ? 'html' :
            mime === jsonType ? 'json' :
                scriptTypeRE.test(mime) ? 'script' :
                    xmlTypeRE.test(mime) && 'xml') || 'text';
    }

    function appendQuery(url, query) {
        if (query === '') {
            return url;
        }
        return (url + '&' + query).replace(/[&?]{1,2}/, '?');
    }

    function serialize(params, obj, traditional, scope) {
        var type,
            array = $B.isArrayFn(obj),
            hash = $B.isPlainObjectFn(obj);
        var keys = Object.keys(obj);
        for(let i =0 ; i < keys.length ;i++){
            let key = keys[i];
            let value = obj[key];
            if (scope) {
                key = traditional ? scope :
                    scope + '[' + (hash || type === 'object' || type === 'array' ? key : '') + ']';
            }
            // handle data in serializeArray() format
            if (!scope && array) {
                params._addFN(value.name, value.value);
            } else if (type === "array" || (!traditional && type === "object")) {// recurse into nested objects
                serialize(params, value, traditional, key);
            } else {
                params._addFN(key, value);
            }
        }        
    }

    function object2param(obj, traditional) {
        var params = [];
        params._addFN = function (key, value) {
            if (typeof value === "function") {
                value = value();
            }
            if (value === null) {
                value = "";
            }
            this.push(escape(key) + '=' + escape(value));
        };
        serialize(params, obj, traditional);
        params._addFN = undefined;
        return params.join('&').replace(/%20/g, '+');
    }

    // serialize payload and append it to the URL for GET requests
    function serializeData(options) {       
        if (options.processData && options.data && typeof (options.data) !== "string") {
            options.data = object2param(options.data, options.traditional);
        }
        if (options.data && (!options.type || options.type.toUpperCase() === 'GET' || 'jsonp' === options.dataType)) {
            options.url = appendQuery(options.url, options.data);
            options.data = undefined;
        }  
    }


    $.ajaxJSONP = function (options) {
        if (!('type' in options)) {
            return $.ajax(options);
        }
        var jsonpID = +new Date();
        var _callbackName = options.jsonpCallback,
            callbackName = ($B.isFunctionFn(_callbackName) ? _callbackName() : _callbackName) || ('Zepto' + (jsonpID++)),
            scriptEl = document.createElement('script'),
            originalCallback = window[callbackName],
            responseData,
            abort = function (errorType) {
                $B.DomUtils.trigger(scriptEl,"error");
                //$(script).triggerHandler('error', errorType || 'abort')
            },
            xhr = { abort: abort },
            abortTimeout;


        var scriptFn = function (e, errorType) {
            clearTimeout(abortTimeout);
            $B.DomUtils.offEvents(scriptEl);
            if (e.type === 'error' || !responseData) {
                //error, type, xhr, settings
                ajaxError(null, errorType || 'error', xhr, options);
            } else {
                ajaxSuccess(responseData[0], xhr, options);
            }

            window[callbackName] = originalCallback;
            if (responseData && $B.isFunctionFn(originalCallback)) {
                originalCallback(responseData[0]);
            }
            originalCallback = responseData = undefined;
            $B.DomUtils.remove(scriptEl);
        };
        //$(script).on('load error', );
        $B.DomUtils.addListener(scriptEl, "load", scriptFn);
        $B.DomUtils.addListener(scriptEl, "error", scriptFn);

        if (ajaxBeforeSend(xhr, options) === false) {
            abort('abort');
            return xhr;
        }

        window[callbackName] = function () {
            responseData = arguments;
        };

        scriptEl.src = options.url.replace(/\?(.+)=\?/, '?$1=' + callbackName);
        document.head.appendChild(scriptEl);

        if (options.timeout > 0) {
            let timeout = options.timeout * 1000;
            abortTimeout = setTimeout(() => {
                abort('timeout');
            }, timeout);
            return xhr;
        }
    };
    $.ajax = function (options) {
        var settings = $B.extendObjectFn({}, ajaxSettings, options || {}),
            urlAnchor, hashIndex;

        if (!settings.crossDomain) {
            urlAnchor = document.createElement('a');
            urlAnchor.href = settings.url;
            // cleans up URL for .href (IE only), see https://github.com/madrobby/zepto/pull/1049
            urlAnchor.href = urlAnchor.href;
            settings.crossDomain = (originAnchor.protocol + '//' + originAnchor.host) !== (urlAnchor.protocol + '//' + urlAnchor.host);
        }

        if (!settings.url) {
            settings.url = window.location.toString();
        }

        if ((hashIndex = settings.url.indexOf('#')) > -1) {
            settings.url = settings.url.slice(0, hashIndex);
        }
        if( settings.contentType === "application/json"){
            settings.processData = false;
        }

        serializeData(settings);

        var dataType = settings.dataType,
            hasPlaceholder = /\?.+=\?/.test(settings.url);
        if (hasPlaceholder) {
            dataType = 'jsonp';
        }

        if (settings.cache === false || ((!options || options.cache !== true) && ('script' === dataType || 'jsonp' === dataType))) {
            settings.url = appendQuery(settings.url, '_=' + Date.now());
        }


        if ('jsonp' === dataType) {
            if (!hasPlaceholder) {
                settings.url = appendQuery(settings.url, settings.jsonp ? (settings.jsonp + '=?') : settings.jsonp === false ? '' : 'callback=?');
            }
            return $.ajaxJSONP(settings);
        }

        var mime = settings.accepts[dataType],
            headers = {},
            protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol,
            xhr = settings.xhr(),
            nativeSetHeader = xhr.setRequestHeader,
            abortTimeout;
        var setHeader = function (name, value) {
            headers[name.toLowerCase()] = [name, value];
        };

        if (!settings.crossDomain) {
            setHeader('X-Requested-With', 'XMLHttpRequest');
        }
        setHeader('Accept', mime || '*/*');
        if (mime = settings.mimeType || mime) {
            if (mime.indexOf(',') > -1) {
                mime = mime.split(',', 2)[0];
            }
            xhr.overrideMimeType && xhr.overrideMimeType(mime);
        }
        if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() !== 'GET')) {
            setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded');
        }
        if (settings.headers) {
            let keys = settings.headers;
            keys.forEach(function (key) {
                setHeader(key, settings.headers[key]);
            });
        }
        xhr.setRequestHeader = setHeader;
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                xhr.onreadystatechange = emptyFn;
                clearTimeout(abortTimeout);
                var result,
                    error = false;
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || (xhr.status === 0 && protocol === 'file:')) {
                    dataType = dataType || mimeToDataType(settings.mimeType || xhr.getResponseHeader('content-type'));
                    if (xhr.responseType === 'arraybuffer' || xhr.responseType === 'blob') {
                        result = xhr.response;
                    } else {
                        result = xhr.responseText;
                        try {
                            // http://perfectionkills.com/global-eval-what-are-the-options/
                            // sanitize response accordingly if data filter callback provided
                            result = ajaxDataFilter(result, dataType, settings);
                            if (dataType === 'script') {
                                //(1, eval)(result);
                            } else if (dataType === 'xml') {
                                result = xhr.responseXML;
                            } else if (dataType === 'json') {
                                try{
                                    result = blankRE.test(result) ? null : JSON.parse(result);
                                }catch(e){
                                    if(settings.onErrorEval){
                                        result = blankRE.test(result) ? null : eval('('+result+')');
                                    }else{
                                        throw e;
                                    }
                                }
                            }
                        } catch (e) {
                            error = e;
                        }
                        if (error) {
                            return ajaxError(error, 'parsererror', xhr, settings);
                        }
                    }
                    ajaxSuccess(result, xhr, settings);
                    //脚本支持
                    if (dataType === "html") {
                        setTimeout(()=>{
                            let fragment = document.createDocumentFragment();
                            let wrap = document.createElement("div");
                            wrap.innerHTML = result;
                            fragment.appendChild(wrap);
                            let scriptArray = wrap.querySelectorAll("script");                           
                            let loading = [];
                            let jsExeTag = [];
                            let onLoadfN = function(){
                                loading.shift();
                                document.head.removeChild(this);
                            };
                            let max = 1;
                            for (let i = 0; i < scriptArray.length; i++) {
                                let script = scriptArray[i].textContent;     
                                let src = scriptArray[i].src;                                                          
                                let scriptel = document.createElement("script");
                                scriptel.type="text/javascript";
                                if(src){
                                    loading.push(1);
                                    scriptel.onload = onLoadfN;
                                    scriptel.onerror = onLoadfN;
                                    scriptel.src = src;
                                    document.head.appendChild(scriptel);
                                    max++;
                                }else{
                                    scriptel.text = script;
                                    jsExeTag.push(scriptel);
                                }                        
                            }
                            if(jsExeTag.length > 0){
                                let count = 0;
                                max = max * 5 * 4;
                                let ivt = setInterval(()=>{
                                    if( loading.length === 0 || count > max){
                                        clearInterval(ivt);
                                        for(let i =0 ; i < jsExeTag.length ;i++){
                                            document.head.appendChild(jsExeTag[i]);
                                            document.head.removeChild(jsExeTag[i]);
                                        }
                                        jsExeTag =undefined;
                                    }                                   
                                    count++;
                                },300);
                            }
                        },1);
                    }
                } else {
                    ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings);
                }
            }
        };

        if (ajaxBeforeSend(xhr, settings) === false) {
            xhr.abort();
            ajaxError(null, 'abort', xhr, settings);
            return xhr;
        }
        if(settings.onProgress){
            xhr.upload.addEventListener('progress', function (e) {
                var progressRate = Math.round((e.loaded / e.total) * 100 );
                if(progressRate > 100){
                    progressRate = 100;
                }                
                settings.onProgress(progressRate);
            })
        }

        var async = 'async' in settings ? settings.async : true;
        xhr.open(settings.type, settings.url, async, settings.username, settings.password);

        if (settings.xhrFields) {
            let keys = settings.xhrFields;
            keys.forEach(function (key) {
                xhr[key] = settings.xhrFields[key];
            });
        }
        let keys = Object.keys(headers);
        keys.forEach(function (key) {
            nativeSetHeader.apply(xhr, headers[key]);
        });

        if (settings.timeout > 0) {
            let timer = settings.timeout * 1000;
            abortTimeout = setTimeout(() => {
                xhr.onreadystatechange = emptyFn;
                xhr.abort();
                ajaxError("timeout", 'timeout', xhr, settings);
            }, timer);
        }
        let sendData = null;
        if(settings.data){
            sendData = settings.data;
            if(settings.contentType === "application/json"){
                sendData = JSON.stringify(sendData);
            }
        }
        xhr.send(sendData);
        return xhr;
    };
})($B);

_extendObjectFn($B, {
    /**
     *打开一个窗口
    *arg={
            full:false,//是否满屏，当为true时候，高宽无效  
            autoHeight:true,//自动根据内容设置高度
            size: { width: 'auto', height: 'auto' },         
            title: '', //标题
            isTop: false,
            iconCls: null, //图标class，font-awesome字体图标
            iconColor: undefined,//图标颜色
            headerColor: undefined,//头部颜色
            toolbar: null, //工具栏对象参考工具栏组件配置说明，可以是创建函数
            toolbarStyle: undefined,//参考工具栏样式定义
            shadow: true, //是否需要阴影
            radius: undefined, //圆角px定义
            header: true, //是否显示头部
            zIndex: 200000000,//层级
            content: null, //静态内容
            url: '',//请求地址
            dataType: 'html', //当为url请求时，html/json/iframe
            draggable: false, //是否可以拖动
            moveProxy: false, //是否代理移动方式
            draggableHandler: 'header', //拖动触发焦点
            closeable: false, //是否关闭
            closeType: 'hide', //关闭类型 hide(隐藏，可重新show)/ destroy 直接从dom中删除
            expandable: false, //可左右收缩
            maxminable: false, //可变化小大
            collapseable: false, //上下收缩
            resizeable: false,//右下角拖拉大小
            onResized: null, //function (pr) { },//大小变化事件
            onLoaded: null, //function () { },//加载后
            onClose: null, //关闭前
            onClosed: null, //function () { },//关闭后
            onExpanded: null, // function (pr) { },//左右收缩后
            onCollapsed: null, // function (pr) { }//上下收缩后
            onCreated: null //function($content,$header){} panel创建完成事件
        }
    返回一个具有close(timeout) api的对象
    ***/
    window: function (args) {
        if (!$B.Panel) {
            alert("Panel is not find!");
            return;
        }
        var _$body, mask = true;
        if (args.isTop) {
            _$body = $B.DomUtils.css(window.top.document.body, { "position": "relative" });
        } else {
            _$body = $B.getBody();
        }
        var _bodyw = parseInt($B.DomUtils.outerWidth(_$body)),
            _bodyh = parseInt($B.DomUtils.outerHeight(_$body));
        if (typeof args.mask !== 'undefined') {
            mask = args.mask;
        }
        if (args.full) {
            mask = false;
            args.size = { width: _bodyw , height: _bodyh };
        } else if (!args.size) {
            args.size = { width: 600, height: 500 };
        }
        if(args.width){
            args.size.width = args.width;
        }
        if(args.height){
            args.size.height = args.height;
        }
        if(typeof args.size.width === "string" ){
            if(args.size.width.indexOf("%")){
                args.size.width = parseFloat(args.size.width.replace("%","")) / 100 * _bodyw;
            }else{
                args.size.width = parseFloat(args.size.width);
            }
        }
        if(typeof args.size.height === "string" ){
            if(args.size.height.indexOf("%")){
                args.size.height = parseFloat(args.size.height.replace("%","")) / 100 * _bodyh;
            }else{
                args.size.height = parseFloat(args.size.height);
            }
        }
        if (args.fixed || args.full) {
            args.draggable = false;
            args.collapseable = false;
            args.maxminable = false;
            args.resizeable = false;
        }
        if(!args.zIndex){
            args.zIndex = 2000000000;
        }
        let avH = _bodyh / 2;
        //自动内容高度
        var auto = typeof args.autoHeight !== "undefined" ? args.autoHeight : true;
        if (auto && args.content) {
            let cc = typeof args.content === "string" ? args.content : args.content.outerHTML;
            let visualWidth = args.size.width - 10;
            let visual = $B.DomUtils.createEl("<div style='position:absolute;top:-999999px;z-index:0;width:" + visualWidth + "px'>" + cc + "</div>");
            $B.DomUtils.append(_$body, visual);
            let h = visual.clientHeight + 2;
            if (h < 35) {
                h = 35;
            }
            if (typeof args.header === "undefined" || args.header) {
                h = h + 35;
            }
            let maxH = _bodyh - 100;
            if (h > maxH) {
                h = maxH;
            }
            $B.DomUtils.remove(visual);
            if (args.toolbar) {
                h = h + 35;
            }
            args.size.height = Math.floor( h);
        }
        var _l = (_bodyw - args.size.width) / 2;
        var _t = (_bodyh - args.size.height) / 2 ;
        avH = _bodyh / 5;
        if(_t > avH){
            _t = avH;
        }
        _t = _t + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
        var $mask = $B.DomUtils.getChildrenById(_$body, "k_window_mask_bg");
        var uuid = this.generateMixed(6);
        if (mask) {
            var mskCss = {};
            var maskWidth = parseInt(_$body.scrollWidth - 1);
            var maskHeight = parseInt(_$body.scrollHeight - 1);
            if (!$mask) {
                $mask = $B.DomUtils.createEl("<div style='z-index:" +  (args.zIndex - 2) + ";position:abosulte;width:" + maskWidth + "px;height:" + maskHeight + "px' for='" + uuid + "' id='k_window_mask_bg'></div>");
                $B.DomUtils.append(_$body, $mask);
            } else {
                mskCss = { width: maskWidth, height: maskHeight };
            }
            if (args.opacity) {
                mskCss["opacity"] = args.opacity;
            }
            if ($B.DomUtils.isHide($mask)) {
                mskCss["top"] = 0;
                $B.DomUtils.css($mask, mskCss);
                $B.DomUtils.show($mask);
                $B.DomUtils.attribute($mask, { "for": uuid });
            } else {
                $B.DomUtils.css($mask, mskCss);
            }
        }
        var $win = $B.DomUtils.createEl("<div  id='" + uuid + "' style='position:absolute;z-index:" + args.zIndex + ";' class='k_window_main_wrap'></div>");
        var posIsPlaintObj, bodyOverflow, velocity2pos;
        if (args.position) {
            posIsPlaintObj = $B.isPlainObjectFn(args.position);
            if (posIsPlaintObj) {
                $B.DomUtils.css($mask, args.position);
                $B.DomUtils.append(_$body, $win);
            } else {
                let winCss, hidepos = -888888;
                velocity2pos = args.position;
                if (args.position === "bottom") {
                    bodyOverflow = $B.DomUtils.css(_$body, "overflow");
                    $B.DomUtils.css(_$body, { "overflow": "hidden" });
                    winCss = {
                        bottom: hidepos,
                        right: 0
                    };
                } else {
                    winCss = {
                        top: hidepos,
                        left: _l
                    };
                }
                $B.DomUtils.css($win, winCss);
                $B.DomUtils.append(_$body, $win);
            }
        } else {
            if (_t < 1) {
                _t = 0;
            }
            if (_l < 1) {
                _l = 0;
            }
            $B.DomUtils.css($win, {
                top: _t,
                left: _l
            });
            $B.DomUtils.append(_$body, $win);
        }
        var panel, closeTimer,
            defOpt = $B.config && $B.config.winDefOpts ? $B.config.winDefOpts : {
                iconCls: "fa-popup", //图标class，font-awesome字体图标
                iconColor: "#6A50FC",//图标颜色
                shadow: true, //是否需要阴影
                radius: "2px", //圆角px定义
                header: true, //是否显示头部
                zIndex: 2147483647,//层级
                dataType: 'html', //当为url请求时，html/json/iframe
                triggerHide:true, //触发全局隐藏
                draggable: true, //是否可以拖动
                moveProxy: false, //是否代理移动方式
                draggableHandler: 'header', //拖动触发焦点
                closeable: true, //是否关闭
                closeType: 'destroy', //关闭类型 hide(隐藏，可重新show)/ destroy 直接从dom中删除
                expandable: false, //可左右收缩
                maxminable: true, //可变化小大
                collapseable: true, //上下收缩
                resizeable: true//右下角拖拉大小 
            };
        var opts = $B.extendObjectFn({}, defOpt, args);
        opts.onClosed = function () { //关闭后
            clearTimeout(closeTimer);
            if ($mask) {
                $B.DomUtils.hide($mask);
            }
            if (typeof args.onClosed === 'function') {
                setTimeout(() => {
                    args.onClosed();
                }, 1);
            }
        };
        if (args.timeout && args.timeout < 5) {
            opts.closeable = false;
        }
        if (args.isTop) {
            $B.DomUtils.css($win, { "top": -888888 });
            if (window.top.$B) {
                $B.DomUtils.attribute($win, { "istop": 1 });
                panel = new window.top.$B.Panel($win, opts);
                $B.velocity($win, { top: 1 }, { duration: 500 });
            }
        }
        if (!panel) {
            panel = new $B.Panel($win, opts);
        }
        if (args.timeout) {
            closeTimer = setTimeout(() => {
                if (opts.closeType === "destroy") {
                    panel.destroy();
                } else {
                    panel.close(true);
                }
            }, args.timeout * 1000);
        }
        if (velocity2pos) {
            let vcss, existEls, fix = 0;
            if (velocity2pos === "bottom") {
                existEls = $B.DomUtils.children(_$body, ".k_window_bottom_");
                vcss = { bottom: 0, right: 2 };
                $B.DomUtils.addClass(panel.elObj, "k_window_bottom_");
            } else {
                vcss = { top: 0 };
                existEls = $B.DomUtils.children(_$body, ".k_window_top_");
                $B.DomUtils.addClass(panel.elObj, "k_window_top_");
            }
            for (let i = 0; i < existEls.length; i++) {
                if ($B.DomUtils.css(existEls[i], "display") !== "none") {
                    fix = fix + existEls[i].clientHeight + 3;
                }
            }
            if (typeof vcss.bottom !== "undefined") {
                vcss.bottom = vcss.bottom + fix;
            } else {
                vcss.top = vcss.top + fix;
            }
            $B.velocity(panel.elObj, vcss, { duration: 360 });
        }
        return panel;
    },
    /***
     *{
            mask:false,
            title:'',
            position:'top',
            content:'提示信息！',
            closeable:false,
            width:宽度,
            onClosed:fn
     }
     *****/
    busyTip: function (args) {
        var title;
        let isStr = typeof args === "string";
        if (args) {
            title = isStr ? args : args.title;
        }
        if (!title) {
            title = $B.config ? $B.config.busyTipTitle : 'please waiting.......';
        }
        let content = "<div><p class='k_processing_top_tip' style='text-align:center;'><i class='fa fa-spin5 animate-spin'></i><span style='padding-left:10px'>" + title + "</span></p></div>";
        var ops = {
            header: false,
            mask: false,
            position: 'top',
            closeable: false, //是否关闭
            draggable: false, //是否可以拖动
            expandable: false, //可左右收缩
            maxminable: false, //可变化小大
            collapseable: false, //上下收缩
            resizeable: false,//右下角拖拉大小
            size: { width: 230 },
            content: content
        };
        if (args && !isStr) {
            ops = $B.extendObjectFn(ops, args);
        }
        return this.window(ops);
    },
    _getToolTipos: function (el, message, fixPos) {
        let shiftPos;
        if (fixPos && typeof fixPos !== "string") {
            shiftPos = fixPos;
            fixPos = undefined;
        }
        if(typeof el["fixpos"] === "object"){
            shiftPos = el["fixpos"];
            el["fixpos"] = undefined;
        }
        let w = 8, h = 8, pos;
        var _$body = $B.getBody();
        if ($B.DomUtils.isNode(el)) {
            w = w + $B.DomUtils.outerWidth(el);
            h = h + $B.DomUtils.outerHeight(el);
            pos = $B.DomUtils.offset(el);
        }
        let scrTop = $B.DomUtils.scrollTop(document);
        let scrLeft = $B.DomUtils.scrollLeft(document);
        let elLeft = pos.left;
        let elTop = pos.top;
        let bodyWidth = _$body.offsetWidth + scrLeft;
        let bodyHeight = _$body.offsetHeight + scrTop;
        let r = 0.95;
        if(bodyWidth > 800){
            r = 0.85;
        }else if(bodyWidth > 1000){
            r = 0.8;
        }else if(bodyWidth > 1300){
            r = 0.7;
        }else if(bodyWidth > 1500){
            r = 0.6;
        }
        var maxWidth =  bodyWidth * r  ;
        let visual = $B.DomUtils.createEl("<span class='k_tool_tip_helper k_box_size' style='max-width:" + maxWidth + "px;position:absolute;top:-10000px;left:-10000px;z-index:0;padding:5px'><p style=''><i style='' class='fa fa-info-1'></i><span style='padding-left:8px'>" + message + "</span></p></span>");
        $B.DomUtils.append(_$body, visual);
        let charWidth = Math.ceil($B.DomUtils.outerWidth(visual));
        let charHeight = Math.ceil($B.DomUtils.outerHeight(visual));
        $B.DomUtils.remove(visual);
        //检测放置合适的位置 transform: rotate(90deg)
        // 1，先检测右侧是否够空间，不够放下方，下方不够放上方，上方不够放右侧
        let isOk = false, iconCss;
        let avaiWidth = bodyWidth - pos.left - w;
        if ((!fixPos && avaiWidth > charWidth) || (fixPos === "right")) {
            isOk = true;
            pos.left = pos.left + w;
            let aviHeight = bodyHeight - pos.top;
            let diff = 0;
            if (aviHeight < charHeight) {
                diff = charHeight - aviHeight + 1;
                pos.top = pos.top - diff;
            }
            iconCss = {
                transform: "rotate(180deg)",
                top: diff + 'px',
                left: '-8px'
            };
        }
        if (!isOk) { //放下方           
            pos.left = bodyWidth - charWidth;
            if (pos.left > elLeft) {
                pos.left = elLeft;
            }
            pos.top = pos.top + h;
            let aviHeight = bodyHeight - pos.top;
            let diff = elLeft - pos.left + 2;
            if (diff < 2) {
                diff = 2;
            }
            iconCss = {
                transform: "rotate(270deg)",
                top: '-12px',
                left: diff + "px"
            };
            let isfixBottom = fixPos === "bottom";
            if (!isfixBottom) {
                //检测底部是否够空间
                if ((aviHeight < charHeight && !fixPos) || (fixPos === "top")) {
                    pos.top = elTop - charHeight - 6;
                    delete iconCss.top;
                    iconCss.bottom = "-12px";
                    iconCss.transform = "rotate(90deg)";
                }
            }
        }   
        if(shiftPos){
            if(shiftPos.top ){
                pos.top = pos.top + shiftPos.top;
            }
            if(shiftPos.left ){
                pos.left = pos.left + shiftPos.left;
            }
        }     
        return {
            pos: pos,
            iconCss: iconCss,
            maxWidth: maxWidth + 20,
            charWidth: charWidth
        };
    },
    /*****
     * pos:元素，或者位置
     * msgFn:提示信息/或者返回信息的函数
     * timeout:关闭时间 或者 up 、right 、bottom 位置信息
     * color:背景色
     * *******/
    toolTip: function (pos, msgFn, timeout,color) {
        let id = $B.getUUID();
        var _$body = $B.getBody();
        let targetEl = pos;
        if ($B.DomUtils.isNode(pos)) {
            let tipId = $B.DomUtils.attribute(pos, 'tooltip_id');
            if (tipId) {
                let el = $B.DomUtils.findbyId(_$body, tipId);
                if (el) {
                    $B.DomUtils.remove(el);
                }
            }
            $B.DomUtils.attribute(pos, { "tooltip_id": id });
        }
        let message = msgFn;
        if(typeof msgFn === "function"){
            message = msgFn();
        }
        let res = this._getToolTipos(pos, message, timeout);
        let charWidth = res.charWidth;
        let maxWidth = res.maxWidth;
        pos = res.pos;
        let widthcss;
        if (charWidth < maxWidth) {
            widthcss = "width:" + charWidth;
        } else {
            widthcss = "max-width:" + maxWidth;
        }
        let iconCss = res.iconCss;
        let txtHtml;
        if(message.indexOf("</") < 0){
            txtHtml = "<p style='text-align:left;padding:0;margin:0;'><i class='fa fa-info-1'></i><span style='padding-left:6px'>" + message + "</span></p>";
        }else{
            txtHtml = "<div>" + message + "</div>";
        }
        let el = $B.DomUtils.createEl("<div  id='" + id + "'  style='" + widthcss + "px;display:none;position:absolute;top:" + pos.top + "px;left:" + pos.left + "px;z-index:" 
        + $B.config.maxZindex + "' class='k_window_tooltip_wrap k_box_size'>"+txtHtml+"<div style='position:absolute;' class='k_tooltip_attrow'><i class='fa fa-play'></i></div></div>");
        let icon = $B.DomUtils.children(el, ".k_tooltip_attrow");
        $B.DomUtils.css(icon, iconCss);
        if(typeof color === "string"){
            el.style.backgroundColor = color;
            icon[0].firstChild.style.color = color;
        }
        $B.DomUtils.append(_$body, el);
        var closeTimer;
        $B.fadeIn(el, {
            duration: 200
        });
        var isTimeout = $B.isNumericFn(timeout);
        let ret = {
            fixPos: isTimeout ? undefined : timeout,
            elObj: el,
            targetEl: targetEl,
            message: msgFn,
            show: function (el, fixPos) {
                let fix =  this.fixPos;
                if (fixPos) {
                    fix = fixPos;
                }
                let msg = this.message;
                if(typeof  this.message === "function"){
                    msg = this.message();
                }
                let res = $B._getToolTipos(el, msg, fix);
                res.pos["max-width"] = res.maxWidth;
                $B.DomUtils.css(this.elObj, res.pos);
                let $icon = $B.DomUtils.children(this.elObj, ".k_tooltip_attrow");
                $B.DomUtils.css($icon, res.iconCss);
                this.elObj.firstChild.lastChild.innerHTML = msg;
                $B.fadeIn(this.elObj, {
                    duration: 200
                });
            },
            hide: function () {
                $B.fadeOut(this.elObj, {
                    duration: 200
                });
            },
            close: function (imdly) {
                let fn =()=>{
                    clearTimeout(closeTimer);
                    this.elObj.instance = undefined;
                    $B.DomUtils.remove(this.elObj);
                    this.message = undefined;
                    this.elObj = undefined;
                    this.close = undefined;
                    this.fixPos = undefined;
                    this.show = undefined;
                    this.hide = undefined;
                    this.targetEl = undefined;
                };
                if(imdly){
                    fn();
                }else{
                    $B.fadeOut(this.elObj, {
                        duration: 200,
                        complete: fn
                    });
                }                
            }
        };
        if (isTimeout) {
            closeTimer = setTimeout(() => {
                ret.close();
            }, timeout * 1000);
        }
        el.instance = ret;
        return ret;
    },
    /**
     * 元素绑定鼠标提示
     * el:元素
     * message:提示信息/或者返回信息的函数
     * fixPos :up 、right 、bottom 位置信息
     * color:背景色
     * **/
    mouseTip: function (el, message, fixPos,color) {
        var flag = $B.DomUtils.attribute(el, 'has_tooltip');
        if (!flag) {
            $B.DomUtils.attribute(el, { 'has_tooltip': 1 });
            $B.DomUtils.bind(el, {
                mouseenter: function (e) { 
                    var ins = $B.DomUtils.getData(this, "tooltipInd");
                    if (ins && ins.show) {
                        ins.show(this, fixPos);
                    } else {
                        ins = $B.toolTip(this, message, fixPos,color);
                        $B.DomUtils.setData(this, "tooltipInd", ins);
                    }
                },
                mouseleave: function (e) {
                    var ins = $B.DomUtils.getData(this, "tooltipInd");
                    if (ins && ins.hide) {
                        ins.hide();
                    }
                }
            });
        }
    },
    /**
     *成功信息
    *arg={
            title:'请您确认',
            mask:false,
            position:'top',
            iconCls:'图标样式',
            iconColor:
            content:'提示信息！',
            toolbar:[],//工具栏，如果传入，则不生成默认的按钮
            contentIcon:'内容区域的图标',
            width:宽度
    }
    ***/
    success: function (args) {
        var opts = this._getWinOpt.apply(this, arguments);
        var title = typeof args !== "undefined" ? args.title : undefined;
        if (!title) {
            title = $B.config ? $B.config.successTitle : 'success message';
        }
        opts = $B.extendObjectFn({}, { title: title, iconCls: 'fa-check', iconColor: '#08E358', contentIcon: 'fa-ok-circled' }, opts);
        var win = this._window(opts, "#08E358");
        return win;
    },
    /**
     * message 警告信息对话框
     * opts = {
            title:'请您确认',
            mask:false,
            position:'top',
            iconCls:'图标样式',
            iconColor:
            content:'提示信息！',
            toolbar:[],//工具栏，如果传入，则不生成默认的按钮
            contentIcon:'内容区域的图标',
            width:宽度
    }
    * ***/
    alert: function (args) {
        var opts = this._getWinOpt.apply(this, arguments);
        var title = typeof args !== "undefined" ? args.title : undefined;
        if (!title) {
            title = $B.config ? $B.config.alertTitle : 'alert message';
        }
        opts = $B.extendObjectFn({}, { title: title, iconCls: 'fa-attention-1', iconColor: '#EDA536', contentIcon: 'fa-attention-alt' }, opts);
        var win = this._window(opts, "#EDA536");
        return win;
    },
    /**
     * message 错误信息对话框
     * opts = {
            title:'请您确认',
            mask:false,
            position:'top',
            iconCls:'图标样式',
            iconColor:
            content:'提示信息！',
            toolbar:[],//工具栏，如果传入，则不生成默认的按钮
            contentIcon:'内容区域的图标',
            width:宽度
    }
    * ***/
    error: function (args) {
        var opts = this._getWinOpt.apply(this, arguments);
        var title = typeof args !== "undefined" ? args.title : undefined;
        if (!title) {
            title = $B.config ? $B.config.errorTitle : 'error message';
        }
        opts = $B.extendObjectFn({}, { title: title, iconCls: 'fa-cancel-circled-1', iconColor: '#F72EA7', contentIcon: 'fa-emo-unhappy' }, opts);
        var win = this._window(opts, "#F72EA7");
        return win;
    },
    /**
     *信息提示框
    *args={
            title:'请您确认',
            mask:false,
            position:'top',
            iconCls:'图标样式',
            iconColor:
            content:'提示信息！',
            toolbar:[],//工具栏，如果传入，则不生成默认的按钮
            contentIcon:'内容区域的图标',
            width:宽度
    }
    ***/
    message: function (args) {
        var opts = this._getWinOpt.apply(this, arguments);
        var title = typeof args !== "undefined" ? args.title : undefined;
        if (!title) {
            title = $B.config ? $B.config.messageTitle : 'message';
        }
        opts = $B.extendObjectFn({}, { title: title, iconCls: 'fa-comment', iconColor: '#3BA7EA', contentIcon: 'fa-comment-1' }, opts);
        var win = this._window(opts, "#3BA7EA");
        return win;
    },
    _getWinOpt: function (args) {
        var opts = {
            width: args.width ? args.width : 400,
            title: undefined, //标题
            shadow: typeof args.shadow !== "undefined" ? args.shadow : true, //是否需要阴影
            mask: typeof args.mask !== "undefined" ? args.mask : true, //是否需要遮罩层
            position: typeof args.position !== "undefined" ? args.position : undefined,
            timeout: args.timeout,
            onClosed:typeof args.onClosed === "function" ? args.onClosed : undefined,
            collapseable: false,
            maxminable: false,
            resizeable: false,
            closeable: typeof args.closeable !== "undefined" ? args.closeable : true
        };
        if (args.iconCls) {
            opts.iconCls = args.iconCls;
        }
        if (args.iconColor) {
            opts.iconColor = args.iconColor;
        }
        if (args.contentIcon) {
            opts.contentIcon = args.contentIcon;
        }
        var content;
        if (typeof args === "string") {
            content = args;
            if (arguments.length >= 2) {
                if ($B["isNumericFn"](arguments[1])) {
                    opts.timeout = arguments[1];
                } else {
                    opts.position = arguments[1];
                }
            }
        } else if (args.content) {
            content = args.content;
        }
        opts.content = content;
        if (typeof args.toolbar !== "undefined") {
            opts["toolbar"] = args.toolbar;
        }
        return opts;
    },
    /**
     * 确认提示框
     * args={
            title:'请您确认',
            iconCls:'图标样式',
            content:'提示信息！',
            toolbar:[],//工具栏，如果传入，则不生成默认的按钮
            contentIcon:'内容区域的图标',
            width:width ,//宽度        
            okIcon :"fa-ok-circled",
            noIcon : "fa-ok-circled",
            okText : "确认",           
            noText : "取消",
            okFn:fn, //确认回调
            noFn:fn, //否定回调
    }
    * ***/
    confirm: function (args) {        
        let title = args.title;
        if (!title) {
            title = $B.config ? $B.config.confirmTitle : 'please confirm';
        }
        var opts = {
            size: { width: args.width ? args.width : 400 },
            title: title, //标题
            iconCls: args.iconCls ? args.iconCls : 'fa-question', //图标cls，对应icon.css里的class
            shadow: typeof args.shadow !== "undefined" ? args.shadow : true, //是否需要阴影
            mask: typeof args.mask !== "undefined" ? args.mask : true, //是否需要遮罩层
            iconColor: typeof args.iconColor !== "undefined" ? args.iconColor : undefined,
            position: typeof args.position !== "undefined" ? args.position : undefined,
            collapseable: false,
            maxminable: false,
            resizeable: false,
            contentIcon: args.contentIcon ? args.contentIcon : "fa-help-1"
        };
        var okFn = args.okFn,
            noFn = args.noFn;
        var okIcon = args.okIcon ? args.okIcon : "fa-ok-circled",
            okText = args.okText ? args.okText : $B.config ? $B.config.buttonOkText : 'submit',
            noIcon = args.noIcon ? args.noIcon : "fa-reply-all",
            noText = args.noText ? args.noText : $B.config ? $B.config.buttonCancleText : 'cancel';
        var content, win;
        if (typeof args === "string") {
            content = args;
            if (arguments.length >= 2) {
                if (typeof arguments[1] === "function") {
                    okFn = arguments[1];
                }
            }
            if (arguments.length === 3) {
                if (typeof arguments[2] === "function") {
                    noFn = arguments[2];
                }
            }
            if (arguments.length === 4) {
                if (typeof arguments[3] === "function") {
                    opts.onClosed = arguments[3];
                }
            }
        } else if (args.content) {
            content = args.content;
        }
        opts.content = content;
        if (typeof args.toolbar === "function") {
            opts["toolbar"] = args.toolbar;
        } else {
            opts["toolbar"] = function () {
                var wrap = this;
                setTimeout(() => { $B.DomUtils.css(wrap, { "padding-bottom": 0 }); }, 1);
                var tool = $B.DomUtils.append(wrap, "<div class='k_confirm_buttons_wrap'></div>");
                var ybtn = $B.DomUtils.append(tool, "<button class='yes'><i   class='fa " + okIcon + "'>\u200B</i>" + okText + "</button>");
                $B.DomUtils.click(ybtn, function () {
                    var goClose = true;
                    if (typeof okFn === "function") {
                        var res = okFn();
                        if (typeof res !== "undefined") {
                            goClose = res;
                        }
                    }
                    if (goClose) {
                        win.close(true);
                    }
                });
                var nbtn = $B.DomUtils.append(tool, "<button class='no'><i  class='fa " + noIcon + "'>\u200B</i>" + noText + "</button>");
                $B.DomUtils.click(nbtn, function () {
                    var goClose = true;
                    if (typeof noFn === "function") {
                        var res = noFn();
                        if (typeof res !== "undefined") {
                            goClose = res;
                        }
                    }
                    if (goClose) {
                        win.close(true);
                    }
                });
                setTimeout(() => {
                    let bg = $B.DomUtils.css(ybtn, "background-color");
                    if ($B.isDeepColor(bg)) {
                        ybtn.style.color = "#ffffff";
                    } else {
                        ybtn.style.color = "#1A242C";
                    }
                    bg = $B.DomUtils.css(nbtn, "background-color");
                    if ($B.isDeepColor(bg)) {
                        nbtn.style.color = "#ffffff";
                    } else {
                        nbtn.style.color = "#1A242C";
                    }
                }, 0);
                return tool;
            };
        }
        if(args.onClosed){
            opts.onClosed = args.onClosed;
        }
        win = this._window(opts, '#B2894B');
        return win;
    },
    _window: function (args, iconColor) {
        let title = args.title;
        if (!title) {
            title = $B.config ? $B.config.confirmTitle : 'please set windwo title';
        }
        var opts = {
            size: { width: args.width ? args.width : 400 },
            title: title, //标题
            iconCls: args.iconCls ? args.iconCls : 'fa-question', //图标cls，对应icon.css里的class
            shadow: typeof args.shadow !== "undefined" ? args.shadow : true, //是否需要阴影
            mask: typeof args.mask !== "undefined" ? args.mask : true, //是否需要遮罩层
            timeout: typeof args.timeout !== "undefined" ? args.timeout : undefined,
            iconColor: typeof args.iconColor !== "undefined" ? args.iconColor : undefined,
            position: typeof args.position !== "undefined" ? args.position : undefined,
            collapseable: false,
            maxminable: false,
            resizeable: false,
            closeable: args.closeable,
            toolbar: args.toolbar
        };
        var win,
            contentIcon = args.contentIcon ? args.contentIcon : "fa-help-1";
        var content;
        if (typeof args === "string") {
            content = args;
        } else if (args.content) {
            content = args.content;
        }
        let id = "c" + $B.generateMixed(8);
        if (typeof ccontent === "string" || !content) {
            content = '<div style="position:relative;min-height:35px"><div id="' + id + '" class="k_box_size" style="border-left:50px solid #fff;"><p>' + content + '</p></div><div  class="k_box_size" style="position:absolute;top:2px;left:1px; height:100%;padding:0px 10px;"><i style="line-height:35px;font-size:32px;color:' + iconColor + '" class="fa ' + contentIcon + '"></i></div></div>';
        } else {
            let el = content;
            content = $B.DomUtils.createEl('<div style="position:relative;min-height:35px"><div id="' + id + '" class="k_box_size" style="border-left:50px solid #fff;"><p></p></div><div  class="k_box_size" style="position:absolute;top:2px;left:1px; height:100%;padding:0px 10px;"><i style="line-height:35px;font-size:32px;color:' + iconColor + '" class="fa ' + contentIcon + '"></i></div></div>');
            let pel = $B.DomUtils.findByTagName(content, "p");
            $B.DomUtils.append(pel, el);
        }
        opts.content = content;
        opts.onCreated = function ($body) {
            let sp = $B.DomUtils.findbyId($body, id);
            let $p = $B.DomUtils.children(sp, "p")[0];
            if ($p.clientHeight < 30) {
                $B.DomUtils.css($p, { "line-height": "36px" });
            }
        };
        opts.onClosed = args.onClosed;
        win = this.window(opts);
        return win;
    }
});
var CHARSArr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
var $spen_CharWidth;
/*********原生扩展***********/
Date.prototype.format = function (format) {
    var date = {
        "M+": this.getMonth() + 1,
        "d+": this.getDate(),
        "h+": this.getHours(),
        "m+": this.getMinutes(),
        "s+": this.getSeconds(),
        "q+": Math.floor((this.getMonth() + 3) / 3),
        "S+": this.getMilliseconds()
    };
    if (/(y+)/i.test(format)) {
        format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
    }
    for (var k in date) {
        if (new RegExp("(" + k + ")").test(format)) {
            format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
        }
    }
    return format;
};
// 解决四维运算,js计算失去精度的问题,仅支持5位小数点 
function _fixsStrNUM(n){
    let s = n.toString();
    if(s.indexOf(".") > 0){
        let arr = s.split(".");
        let len = arr[1].length;
        if(len > 10){
            len = 10;
            n = parseFloat(arr[0]+"."+arr[1].substring(0,5));
        }
        return {
            n:n,
            r:len
        }
    }
    return {
        n:n,
        r:1
    };
}
//加法   
Number.prototype.add = function (arg) {
    var r1 = _fixsStrNUM(this);
    var r2 =  _fixsStrNUM(arg);
    var m = r1.r > r2.r ? r1.r : r2.r;  
    m = Math.pow(10,m);
    return (r1.n * m + r2.n * m) / m;
};
//减法   
Number.prototype.sub = function (arg) {
    return this.add(-arg);
};
//乘法   
Number.prototype.mul = function (arg) {
    var m = 0, s1 = this.toString(), s2 = arg.toString();
    try { m += s1.split(".")[1].length } catch (e) { }
    try { m += s2.split(".")[1].length } catch (e) { }
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
};
//除法   
Number.prototype.div = function (arg) {
    var t1 = 0, t2 = 0, r1, r2;
    try { t1 = this.toString().split(".")[1].length } catch (e) { }
    try { t2 = arg.toString().split(".")[1].length } catch (e) { }
    with (Math) {
        r1 = Number(this.toString().replace(".", ""))
        r2 = Number(arg.toString().replace(".", ""))
        return (r1 / r2) * pow(10, t2 - t1);
    }
};
//十六进制颜色值的正则表达式
var HexReg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
/****变量定义******/
var ajaxOpts = {
    waiting: false,
    timeout: 2000 * 60,
    type: "POST",
    dataType: 'json',
    contentType: undefined,
    notEncode: false,
    async: true,
    onErrorEval: false,
    processData: true,
    cache: false,
    dataFilter: undefined,//fn(data, type) 参数过滤处理
    beforeSend: undefined, //fn(xhr, settings) 返回false则不执行
    error: function (xhr, status, errorThrown) {
        this.removeWaiting();
        this.recoverButton();
        var res = status === "timeout" ? "timeout  error!" : "http status " + xhr.status;
        if (window.console) {
            console.log(xhr.responseText);
        }
        try {
            res = eval('(' + xhr.responseText + ')');
        } catch (e) {
        }
        this.onReturn(res, status, xhr);
        this.fail(res, status, xhr);
        this.final(res, status, xhr);
        console.log(xhr.responseText);
    },
    success: function (res, status, xhr) {
        this.removeWaiting();
        this.recoverButton();
        this.onReturn(res, status, xhr);
        if (typeof res.code !== "undefined") {
            if (res.code === 0) {
                var data = res.data;
                if (res.strConvert) {
                    data = eval('(' + res.data + ')');
                }
                this.ok(res.message, data, res);
            } else if (res.code === 99999) {
                if (res.data === "notlogin") {
                    $B.error(res.message);
                    setTimeout(function () {
                        if (window.ctxPath) {
                            window.top.location = $B.getHttpHost(window.ctxPath);
                        }
                    }, 1600);
                } else {
                    var permission = "this is not permission";
                    if ($B.config && $B.config.permission) {
                        permission = $B.config.permission;
                    }
                    $B.error(permission);
                }
            } else {
                this.fail(res.message, res);
            }
        } else {
            this.ok(res, res);
        }
        this.final(res, status, xhr);
    },
    /**
     *当返回结果是正确时的处理
     *data:返回的数据
     *message:提示的信息
     **/
    ok: function (message, data) {
    },
    /***
     *当返回结果是非正确时的处理
     ***/
    fail: function (msg, res) {
        let $b = $B.getBody();
        if ($B.DomUtils.getChildrenByClass($b, "._request_fail_window_").length === 0) {
            let errWin = $B.error(msg, 2);
            $B.DomUtils.addClass(errWin.elObj, "_request_fail_window_");
            if (msg.indexOf("not login") >= 0) {
                window.top.location.href = $B.getHttpHost(window.ctxPath);
            }
        } else {
            console.log(" fail fail 》》》》》》》》》》》》》》》 ", msg, res);
        }
    },
    onReturn: function (res, status, xhr) {
    },
    /**
     * 无论如何都回调的函数
     ****/
    final: function (res, status, xhr) { //无论成功，失败，错误都执行的回调
    },
    recoverButton: function () {
        if (this["target"]) {
            //this["target"].removeAttribute("disabled");
            $B.DomUtils.removeAttribute(this["target"], "disabled");
            $B.DomUtils.html(this["target"], this.recoverText);
            this["target"] = undefined;
        }
    },
    removeWaiting: function () {
        if (this.waiting) {
            this.waiting = undefined;
            this.waitingObj.close();
            this.waitingObj = undefined;
        }
    }
};
_extendObjectFn($B, {
    iframeHtml: "<iframe  class='' frameborder='0' style='overflow:visible;height:100%;width:100%;display:block;vertical-align:top;'  src='' ></iframe>",
    loadingHtml: "<div class='k_box_size k_loading_el' style='position:absolute;z-index:2147483600;width:100%;height:26px;top:2px;left:0;' class='loading'><div class='k_box_size' style='opacity: 0.5;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2147483600;background-color:loadingBackground'></div><div class='k_box_size' style='width:100%;height:100%;line-height:26px;padding-left:16px;position:absolute;width:100%;height:100%;z-index:2147483611;color:#fff;text-align:center;'><i style='color:#fff;font-size:16px;' class='fa animate-spin fa-spin6'></i><span style='padding-left:5px;font-weight:normal;color:#fff;'>loadingTxt</span></div></div>",
    /**框架的ajax统一入口
     *所有ajax返回均以 res={code:'',message:'',data:{}}的格式返回
    *code=0表示服务器无异常运行并返回结果，code=1时，表示服务器出现异常并返回提示
    *message，用与服务器返回的信息提示
    *data,用于服务器返回的数据，如tree组件、datagrid组件返回的数据就保存到data当中
    args={
            waiting:false ,     //是否显示waiting
            timeout: 1000 * 60, //超时
            type: "POST",       //请求方式
            dataType: 'json',   //请求数据类型
            async: true,        //是否异步
            preRequest: fn,     //请求前，回调
            url:'',             //请求url
            data:{},            //请求参数
            ok:function(message,data){},    //成功回调，message:返回信息，data:返回数据
            fail:function(message){},       //失败回调，message:返回信息
            final:function(res){}           //无论成功/失败都调用的回调 res = {code:'',message:'',data:{}}
    }
    ****/
    request: function () {
        var args = arguments[0];
        var opts;
        if (args !== undefined) {
            opts = _extendObjectFn({}, ajaxOpts, args);
        } else {
            opts = ajaxOpts;
        }
        if (opts.data && typeof opts.data === "object" && opts.data.constructor.name !== "FormData") {
            for (var prop in opts.data) {
                if (opts.data[prop] === null) {
                    delete opts.data[prop];
                } else {
                    if (opts.notEncode) {
                        opts.data[prop] = opts.data[prop];
                    } else {
                        opts.data[prop] = this.htmlEncode(opts.data[prop]);
                    }
                }
            }
        }
        var queue = window["_submit_queues"];
        var submitBtn;
        if (queue && queue.length > 0) {
            let lastIdx = queue.length - 1;
            let diff = queue[lastIdx].date - new Date();
            if (diff <= 500) {//500毫秒内
                submitBtn = queue[lastIdx].btn;
                let q = queue.shift();
                q.btn = undefined;
            }
        }
        if (arguments.length > 1 || submitBtn) {
            let btn = arguments.length > 1 ? arguments[1] : submitBtn;
            opts["target"] = btn;
            $B.DomUtils.attribute(btn, { "disabled": "disabled" });
            let busyIng = "this is processing!";
            if ($B.config && $B.config.busyTipTitle) {
                busyIng = $B.config.busyTipTitle;
            }
            if (btn.nodeName === "INPUT") {
                opts["recoverText"] = btn.innerText;
                btn.val(busyIng);
            } else {
                opts["recoverText"] = btn.innerHTML;
                let color = btn.style.color;
                if (btn.lastChild) {
                    color = btn.lastChild.style.color;
                }
                btn.innerHTML = "<i style='padding:0;color:" + color + ";' class='fa fa-spin6 animate-spin'></i><span style='color:" + color + ";padding-left:5px;'>" + busyIng + "</span>";
            }
        }
        if (opts.waiting) {
            let $w = $B.busyTip({});
            opts.waitingObj = $w;
        }
        $B.ajax(opts);
    },
    forbidSelected: function () {
        document.selection && document.selection.empty && (document.selection.empty(), 1)
            || window.getSelection && window.getSelection().removeAllRanges();
    },
    _getSuitablePos: function ($wrap, targetel, $body) {
        let top, left, arrowLeft, maxHeight;
        let wrapWidth = $B.DomUtils.outerWidth($wrap);
        let fixWidth = $B.DomUtils.attribute(targetel, "fix_width");
        let wrapHeight = $B.DomUtils.outerHeight($wrap);
        if ($B.DomUtils.hasClass($wrap, "k_dropdown_list_wrap")) {
            let childLen = $B.DomUtils.attribute($wrap, "_itlen");
            if (childLen) {
                wrapHeight = 24 * parseInt(childLen);
            } else {
                let itWrap = $wrap.lastChild.firstChild.firstChild;
                if (itWrap.children && itWrap.children.length > 0) {
                    wrapHeight = 24 * itWrap.children.length;
                }
            }
            wrapHeight = wrapHeight + 2;
        }

        let elPos = $B.DomUtils.offset(targetel);
        let elHeight = $B.DomUtils.outerHeight(targetel);
        let elWidth = $B.DomUtils.outerWidth(targetel);
        if (fixWidth) {
            elWidth = parseFloat(fixWidth);
        }
        let bodyHeight = $body.clientHeight;
        let bodyWidth = $body.clientWidth;
        // var scrollTop = $B.DomUtils.scrollTop($body);
        // var scrollLeft = $B.DomUtils.scrollLeft($body);
        // elPos.top = elPos.top - scrollTop;
        // elPos.left = elPos.left - scrollLeft;
        //console.log(" _getSuitablePos = " + JSON.stringify(elPos));


        //先检测右下方是否够空间，确认top位置
        let aviHeight = bodyHeight - elPos.top - elHeight;
        let arrowCss = {};
        if (aviHeight >= wrapHeight || elPos.top < aviHeight) {//空间够
            top = elPos.top + elHeight + 8;
            arrowCss["top"] = -14;
            maxHeight = bodyHeight - top - 5;
            arrowCss["transform"] = "rotate(0)";
        } else if ((elPos.top - 6) > aviHeight) {//上面空间比下面的大
            top = elPos.top - wrapHeight - 6;
            arrowCss["bottom"] = -14;
            arrowCss["transform"] = "rotate(180deg)";
            if (top < 2) {
                top = 2;
            }
            maxHeight = elPos.top - 10;
        } else {
            wrapHeight = aviHeight - 8;
            top = elPos.top + elHeight + 8;
            arrowCss["top"] = -14;
            maxHeight = bodyHeight - top - 5;
            arrowCss["transform"] = "rotate(0)";
        }
        let wwWidth = wrapWidth;
        if (wrapWidth < elWidth) {
            wwWidth = elWidth;
        }
        let suitableWidth = bodyWidth * 0.45;
        let needFix2px = false;
        if (wwWidth > suitableWidth) {
            wwWidth = suitableWidth;
            needFix2px = true;
        }
        left = elPos.left;
        //检测合适的left,这里有问题，需要修正
        // left = elPos.left + parseInt(elWidth / 2) - parseInt(wwWidth / 2);
        // if (left < 2) {
        //     left = 2;
        // } else if ((left + wwWidth) > bodyWidth) {
        //     left = bodyWidth - wwWidth;
        // }
        // if (needFix2px) {
        //     left = left - 2;
        // }
        arrowLeft = elPos.left - left + elWidth / 2 - 9;
        arrowCss["left"] = arrowLeft;
        var res = { arrowPos: arrowCss, pos: { top: top, left: left, width: wwWidth, height: wrapHeight, "max-height": maxHeight } };
        return res;
    },
    _createDropListItems: function (items, opts, $inner, $input, resetHeight) {
        $inner.innerHTML = "";
        if (items.length === 0) {
            let nodata = ($B.config && $B.config.returnEmptyData) ? $B.config.returnEmptyData : 'the return is empty!';
            $inner.innerHTML = "<div style='padding-top:6px' class='k_dropdown_list_item not_data'><i style='color:#FF6D34' class='fa fa-info'></i><span style='padding-left:10px;color:#666;'>" + nodata + "</span></div>";
        } else {
            let wrap = $inner;
            let height = 0;
            for (let i = 0; i < items.length; i++) {
                let txt = opts.textField ? items[i][opts.textField] : items[i].text;
                let id = opts.idField ? items[i][opts.idField] : items[i].id;
                id = id + "";
                let $it = $B.DomUtils.append(wrap, "<div class='k_dropdown_list_item'>" + txt + "</div>");
                $B.DomUtils.attribute($it, { dataid: id });
                if (items[i].selected) {
                    $B.DomUtils.addClass($it, "k_dropdown_item_selected");
                    if ($input) {
                        if (!$B.DomUtils.attribute($input, "readonly") && !$B.DomUtils.attribute($input, "multiple")) {
                            $input.value = items[i].text;
                        }
                        if (opts.multiple || Array.isArray($input.selectedValue)) {
                            let put = true;
                            if (!Array.isArray($input.selectedValue)) {
                                $input.selectedValue = [];
                            } else {
                                let varr = $input.selectedValue;
                                for (let j = 0; j < varr.length; j++) {
                                    if (varr[j].id === id) {
                                        put = false;
                                        break;
                                    }
                                }
                            }
                            if (put) {
                                $input.selectedValue.push({ id: id, text: txt });
                            }
                        } else {
                            $input.selectedValue = [{ id: id, text: txt }];
                        }
                    }
                }
                height = height + 24;
            }
            if (resetHeight) {
                var ddlEl = $inner.parentNode.parentNode.parentNode;
                if ($B.DomUtils.css(ddlEl, "display") === "block") {
                    let body = $B.getBody();
                    let pos = $B.DomUtils.position(ddlEl);
                    let aviHeight = $B.DomUtils.height(body) - pos.top - 10;
                    if (height > aviHeight) {
                        height = aviHeight;
                    }
                    $B.DomUtils.height(ddlEl, height + 2);
                }
            }
        }

    },
    createGlobalBodyHideEv: function () {
        var $body = $B.getBody();
        if (!$B.DomUtils.attribute($body, "has_globel_droplist")) {
            $B.DomUtils.attribute($body, { "has_globel_droplist": 1 });
            $B.DomUtils.mousedown($body, (e) => {
                if (window["_globalDraging"]) {
                    return true;
                }
                let target = e.target;
                while (target) {
                    if (target === $B._0001currentdroplistEl) {
                        $B._0001currentdroplistEl = undefined;
                        return true;
                    }
                    if ($B.DomUtils.hasClass(target, "k_dropdown_list_wrap")) {
                        return true;
                    }
                    target = target.parentNode;
                    if (target.nodeName === "#document" || target.tagName === "BODY") {
                        break;
                    }
                }
                let elArr = $B.DomUtils.children($body, ".k_dropdown_list_wrap");
                if (elArr.length > 0) {
                    for (let i = 0; i < elArr.length; i++) {
                        let el = elArr[i];
                        if (el.style.display !== "none") {
                            $B.slideUp(el, 150);
                            let _dlistgid = $B.DomUtils.attribute(el, "_dlistgid");
                            if (_dlistgid) {
                                let $i = document.getElementById(_dlistgid);
                                if ($i) {
                                    let $ic = $B.DomUtils.children($i, "i");
                                    if ($ic.length > 0) {
                                        $B.animate($ic[0], { "rotateZ": "0deg" }, { duration: 200 });
                                    }
                                }
                            }
                        }
                    }
                }
            });
            let elCachedArr = [], cachedTimer;
            $B.DomUtils.resize(window, (e) => {
                cachedTimer = setTimeout(() => {
                    elCachedArr = [];
                }, 1000);
                if (elCachedArr.length > 0) {
                    for (let i = 0; i < elCachedArr.length; i++) {
                        let el = elCachedArr[i].el;
                        let srcEl = elCachedArr[i].srcEl;
                        let ofs = $B.DomUtils.offset(srcEl);
                        let left = ofs.left;
                        el.style.left = left + "px";
                    }
                } else {
                    let allDdls = $B.DomUtils.children($body, ".k_dropdown_list_wrap");
                    for (let i = 0; i < allDdls.length; i++) {
                        let el = allDdls[i];
                        if (!$B.DomUtils.isHide(el)) {
                            let elId = $B.DomUtils.attribute(el, "_dlistgid");
                            let srcEl = document.getElementById(elId);
                            if (srcEl) {
                                let ofs = $B.DomUtils.offset(srcEl);
                                let left = ofs.left;
                                el.style.left = left + "px";
                                elCachedArr.push({
                                    el: el,
                                    srcEl: srcEl
                                });
                            }
                        }
                    }
                }

            });
        }
    },
    /***
     * el:需要下拉选项的元素
     * items:[{id:id,text:txt,selected:true}]
     * opts:{onClick:fn,        //返回true则执行自动关闭
     *       onCreate:fn,
     *       textField，
     *       idField   
     *       motionless:true    是否静默
     *       multiple:false     是否多选
     *       isTree:false       是否树形
     * }
     * ****/
    createDropList: function (el, items, opts) {
        if (Array.isArray(el)) {
            el = el[0];
        }
        var $wrap;
        var $body = $B.getBody();
        this.createGlobalBodyHideEv();
        var $icon = $B.DomUtils.children(el, "i");
        let globalDownid = $B.DomUtils.attribute(el, "_droplistid");
        if (!globalDownid) {
            let id = $B.getUUID();
            $B.DomUtils.attribute(el, { "_droplistid": id });
            $wrap = $B.DomUtils.createEl("<div style='padding:0;margin:0;width:auto;display:none;z-index:" + $B.config.maxZindex + ";top:-100000px;position:absolute;' id='" + id + "' class='k_dropdown_list_wrap k_box_size'></div>");
            let targetid = $B.DomUtils.attribute(el, "id");
            if (!targetid) {
                targetid = $B.getUUID();
                $B.DomUtils.attribute(el, { "id": targetid });
            }
            $B.DomUtils.attribute($wrap, { "_dlistgid": targetid });
            let $inner = $B.DomUtils.createEl("<div class='k_dropdown_inner' style='position:absolute;top:-1000000000px;width:auto;padding:0;margin:0;'></div>");
            let $input = el.firstChild;
            if ($input.tagName !== "INPUT" && $B.DomUtils.attribute($input, "type") !== "text") {
                $input = undefined;
            }
            if (!opts.onCreate) {
                this._createDropListItems(items, opts, $inner, $input);//
            }
            let defautlClick = true;
            if (opts.onCreate) {
                let ret = opts.onCreate(items, opts, $inner, $input);
                if (typeof ret !== "undefined") {
                    if ($B.isPlainObjectFn(ret)) {
                        defautlClick = ret.defautlClick;
                        $B.DomUtils.attribute($wrap, { "_itlen": ret._itlen });
                    } else {
                        defautlClick = ret;
                    }
                }
            }
            $B.DomUtils.append($body, $inner);
            let h = $B.DomUtils.outerHeight($inner);
            let w = $B.DomUtils.outerWidth($inner);
            if (h < 30) {
                h = 30;
            }
            $B.DomUtils.css($wrap, { width: w + 2, height: h + 2 });
            $B.DomUtils.detach($inner);
            $B.DomUtils.removeAttribute($inner, "style");
            $B.DomUtils.css($inner, { height: '100%', width: '100%' });
            $B.DomUtils.append($wrap, $inner);
            $B.myScrollbar($inner, {});
            $B.DomUtils.prepend($wrap, "<div style='position:absolute;width:12px;' class='_droplist_attrow'><i style='font-size:18px;' class='fa fa-up-dir'></i></div>");
            $B.DomUtils.append($body, $wrap);
            $B.DomUtils.mousedown(el, function () {
                $B._0001currentdroplistEl = this;
            });
            if (defautlClick) {
                $B.DomUtils.click($inner, (e) => {
                    if ($B.DomUtils.hasClass(e.target, "not_data")) {
                        return true;
                    }
                    if ($B.DomUtils.hasClass(e.target, "k_dropdown_list_item")) {
                        let id = $B.DomUtils.attribute(e.target, "dataid");
                        let data = { id: id, text: e.target.innerText };
                        let isSelected = true;
                        if (opts.multiple) { //如果是多选
                            if ($B.DomUtils.hasClass(e.target, "k_dropdown_item_selected")) {
                                $B.DomUtils.removeClass(e.target, "k_dropdown_item_selected");
                                isSelected = false;
                            } else {
                                $B.DomUtils.addClass(e.target, "k_dropdown_item_selected");
                            }
                        } else {
                            let siglings = $B.DomUtils.siblings(e.target);
                            for (let i = 0; i < siglings.length; i++) {
                                if ($B.DomUtils.hasClass(siglings[i], "k_dropdown_item_selected")) {
                                    $B.DomUtils.removeClass(siglings[i], "k_dropdown_item_selected");
                                    break;
                                }
                            }
                            $B.DomUtils.addClass(e.target, "k_dropdown_item_selected");
                        }
                        if (opts.onClick) {
                            setTimeout(() => {
                                if (opts.onClick(data, e.target, isSelected)) {
                                    if ($icon.length > 0) {
                                        $B.animate($icon[0], { "rotateZ": "0deg" }, { duration: 200 });
                                    }
                                    $B.fadeOut($wrap, 260);
                                }
                            }, 1);
                        } else {
                            if ($icon.length > 0) {
                                $B.animate($icon[0], { "rotateZ": "0deg" }, { duration: 200 });
                            }
                            $B.fadeOut($wrap, 260);
                        }
                    }
                });
            }
            $B.DomUtils.click(el, function () {
                $B.createDropList(this);
                if ($B.DomUtils.hasClass(this, "k_combox_wrap")) {
                    if (!$B.DomUtils.attribute(this.firstChild, "readonly")) {
                        this.firstChild.focus();
                    }
                }
            });
            $wrap.hideFn = function () {
                $B.fadeOut(this, 260);
                if ($icon.length > 0) {
                    $B.animate($icon[0], { "rotateZ": "0deg" }, { duration: 200 });
                }
            };
            $wrap.showFn = function () {
                if ($B.DomUtils.css(this, "display") === "none") {
                    $B.createDropList(el);
                }
            };
            $wrap.unSelectedFn = function (dataid) {
                let childs = this.lastChild.firstChild.firstChild.children;
                for (let i = 0; i < childs.length; i++) {
                    if (dataid === $B.DomUtils.attribute(childs[i], "dataid")) {
                        $B.DomUtils.removeClass(childs[i], "k_dropdown_item_selected")
                        break;
                    }
                }
            };
            $wrap.selectedFn = function (dataid) {
                let childs = this.lastChild.firstChild.firstChild.children;
                for (let i = 0; i < childs.length; i++) {
                    if (dataid === $B.DomUtils.attribute(childs[i], "dataid")) {
                        $B.DomUtils.addClass(childs[i], "k_dropdown_item_selected")
                        break;
                    }
                }
            };
            $wrap._clearAllFn = function () {
                $wrap.hideFn = undefined;
                $wrap.showFn = undefined;
                $wrap.selectedFn = undefined;
                $wrap.unSelectedFn = undefined;
                $wrap._clearAllFn = undefined;
                $wrap.clearAll = undefined;
            };
            $wrap.clearAll = $wrap._clearAllFn;
        } else {
            $wrap = $B.DomUtils.children($body, "#" + globalDownid);
            if ($B.DomUtils.css($wrap, "display") === "block") {
                if ($icon.length > 0) {
                    $B.animate($icon[0], { "rotateZ": "0deg" }, { duration: 200 });
                }
                $B.fadeOut($wrap, 260);
                return;
            }
        }
        if (opts && opts.motionless) {
            return $wrap;
        }
        if ($wrap) {
            if ($B.DomUtils.css($wrap, "display") === "none") {
                $B.DomUtils.css($wrap, { "display": "block", "top": "-99999999px" });
            }
            let ret = this._getSuitablePos($wrap, el, $body);
            let $arrow = $B.DomUtils.children($wrap, "._droplist_attrow")[0];
            $B.DomUtils.css($arrow, ret.arrowPos);
            let styleAttr = $B.DomUtils.attribute($arrow, "style");
            let styleObj = $B.style2cssObj(styleAttr);
            if (ret.arrowPos.top) {
                delete styleObj.bottom;
            } else {
                delete styleObj.top;
            }
            styleAttr = $B.cssObj2string(styleObj);
            $B.DomUtils.attribute($arrow, { "style": styleAttr });
            $B.DomUtils.css($wrap, ret.pos);
            $wrap = $B.DomUtils.detach($wrap);
            $B.DomUtils.append($body, $wrap);
            if ($icon.length > 0) {
                $B.animate($icon[0], { "rotateZ": "180deg" }, { duration: 200 });
            }
            let $c = $wrap.lastChild.firstChild.firstChild;
            if ($c.children && $c.children.length > 0) {
                for (let i = 0; i < $c.children.length; i++) {
                    $c.children[i].style.display = "block";
                }
            }
            $B.fadeIn($wrap, 260, function () {
                //获取所有项目的最大宽度，设置每一个项目的width为最大宽度
                let $iner = $wrap.lastChild;
                let tmpArr = $B.DomUtils.children($iner.firstChild.firstChild);
                let maxWidth = 0;
                for (let i = 0; i < tmpArr.length; i++) {
                    if (tmpArr[i].scrollWidth > maxWidth) {
                        maxWidth = tmpArr[i].scrollWidth;
                    }
                }
                if (maxWidth > ret.pos.width) {
                    maxWidth = maxWidth + "px";
                    for (let i = 0; i < tmpArr.length; i++) {
                        tmpArr[i].style.width = maxWidth;
                    }
                }
            });
        }
        return $wrap;
    },
    params2urlString: function (params, encode) {
        if (typeof encode === "undefined") {
            encode = true;
        }
        let keys = Object.keys(params);
        let res = [], val;
        for (let i = 0; i < keys.length; i++) {
            if (encode) {
                val = encodeURIComponent(params[keys[i]]);
            } else {
                val = params[keys[i]];
            }
            res.push(keys[i] + "=" + val);
        }
        res.join("&");
    },
    getIframeEl: function (clazz) {
        var el = $B.DomUtils.createEl($B.iframeHtml);
        if (clazz) {
            $B.DomUtils.addClass(el, clazz);
        }
        return el;
    },
    getIconLoading: function (clazz) {
        let el = $B.DomUtils.createEl("<div class=''><i style='font-size:16px' class='fa fa-spin5'></i></div>");
        if (typeof clazz === "string") {
            $B.DomUtils.addClass(el, clazz);
        } else if ($B.isPlainObjectFn(clazz)) {
            let i = $B.children(el, "i");
            $B.DomUtils.css(i, clazz);
        }
        return el;
    },
    getLoadingEl: function (text, background) {
        let cfg = $B.getLoadingCfg();
        if (!text) {
            text = cfg.text;
        }
        if (!background) {
            background = cfg.color;
        }
        var html = $B.loadingHtml.replace("loadingTxt", text);
        if (background) {
            html = html.replace("loadingBackground", background);
        }
        let el = $B.DomUtils.createEl(html);
        let isDeep = this.isDeepColor(background);
        if (!isDeep) {
            let childs = $B.DomUtils.children(el)[1];
            $B.DomUtils.css(childs, { color: "#666" });
            childs = $B.DomUtils.children(childs);
            $B.DomUtils.css(childs, { color: "#666" });
        }
        return el;
    },
    getLoadingCfg: function () {
        let config = $B["config"];
        let loadingBackground = "#5D39F0";
        let loadingTxt = "this is loading , please waiting!";
        if (config) {
            if (config.loadingBackground) {
                loadingBackground = config.loadingBackground;
            }
            if (config.loading) {
                loadingTxt = config.loading;
            }
        }
        return {
            color: loadingBackground,
            text: loadingTxt
        };
    },
    removeLoading: function (loading, fn) {
        $B.fadeOut(loading, () => {
            $B.DomUtils.remove(loading);
            if (fn) {
                fn();
            }
        }, 200);
    },
    getCharWidth: function (text, fs) {
        if (typeof fs === 'undefined') {
            fs = 14;
        }
        if (!$spen_CharWidth) {
            $spen_CharWidth = $B.DomUtils.createEl("<span style='position:absolute;white-space:nowrap;top:-90000000px;left:10000000px'></span>");
            $B.DomUtils.append($B.getBody(), $spen_CharWidth);
        }
        $spen_CharWidth.style.fontSize = fs + "px";
        var w = 0;
        try {
            $spen_CharWidth.innerText = this.htmlEncode(text);
            w = Math.ceil($B.DomUtils.width($spen_CharWidth));
            setTimeout(function () {
                $spen_CharWidth.innerText = "";
            }, 1);
        } catch (ex) {
            console.log(ex);
        }
        return w;
    },
    /***
     * 是否是深色
     * color: 颜色，支持十六进制或者rgba格式
     * ***/
    isDeepColor: function (color) {
        if (color === "none") {
            return false;
        }
        var tempArray
        if (color.indexOf("#") >= 0) {
            color = $B.hex2RgbObj(color);
            tempArray = [];
            tempArray.push(color.r);
            tempArray.push(color.g);
            tempArray.push(color.b);
        } else {
            let rgbval = color.replace("rgb(", "").replace(")", "");
            tempArray = rgbval.split(",");
        }
        var level = tempArray[0] * 0.299 + tempArray[1] * 0.587 + tempArray[2] * 0.114;
        if (level <= 180) {
            return true;
        } else {
            return false;
        }
    },
    rgb2Hsb: function (arg) {
        var rgb = arg;
        if (typeof rgb === "string") {

        }
        var hsb = {
            h: 0,
            s: 0,
            b: 0
        };
        var min = Math.min(rgb.r, rgb.g, rgb.b);
        var max = Math.max(rgb.r, rgb.g, rgb.b);
        var delta = max - min;
        hsb.b = max;
        hsb.s = max !== 0 ? 255 * delta / max : 0;
        if (hsb.s !== 0) {
            if (rgb.r === max) {
                hsb.h = (rgb.g - rgb.b) / delta;
            } else if (rgb.g === max) {
                hsb.h = 2 + (rgb.b - rgb.r) / delta;
            } else {
                hsb.h = 4 + (rgb.r - rgb.g) / delta;
            }
        } else {
            hsb.h = -1;
        }
        hsb.h *= 60;
        if (hsb.h < 0) {
            hsb.h += 360;
        }
        hsb.s *= 100 / 255;
        hsb.b *= 100 / 255;
        return hsb;
    },
    hex2Hsb: function (hex) {
        var hsb = this.rgb2Hsb(this.hex2RgbObj(hex));
        if (hsb.s === 0) {
            hsb.h = 360;
        }
        return hsb;
    },
    hsb2Hex: function (hsb) {
        return this.rgb2Hex(this.hsb2Rgb(hsb));
    },
    hsb2Rgb: function (hsb) {
        var rgb = {};
        var h = Math.round(hsb.h);
        var s = Math.round(hsb.s * 255 / 100);
        var v = Math.round(hsb.b * 255 / 100);
        if (s === 0) {
            rgb.r = rgb.g = rgb.b = v;
        } else {
            var t1 = v;
            var t2 = (255 - s) * v / 255;
            var t3 = (t1 - t2) * (h % 60) / 60;
            if (h === 360) {
                h = 0;
            }
            if (h < 60) {
                rgb.r = t1;
                rgb.b = t2;
                rgb.g = t2 + t3;
            } else if (h < 120) {
                rgb.g = t1;
                rgb.b = t2;
                rgb.r = t1 - t3;
            } else if (h < 180) {
                rgb.g = t1;
                rgb.r = t2;
                rgb.b = t2 + t3;
            } else if (h < 240) {
                rgb.b = t1;
                rgb.r = t2;
                rgb.g = t1 - t3;
            } else if (h < 300) {
                rgb.b = t1;
                rgb.g = t2;
                rgb.r = t2 + t3;
            } else if (h < 360) {
                rgb.r = t1;
                rgb.g = t2;
                rgb.b = t1 - t3;
            } else {
                rgb.r = 0;
                rgb.g = 0;
                rgb.b = 0;
            }
        }
        return {
            r: Math.round(rgb.r),
            g: Math.round(rgb.g),
            b: Math.round(rgb.b)
        };
    },
    /***
     * rgba颜色转十六进制
     * ****/
    rgb2Hex: function (rgbColor) {
        var that = rgbColor;
        if (/^(rgb|RGB)/.test(that)) {
            var aColor = that.replace(/(?:\(|\)|rgb(a)?|RGB(A)?)*/g, "").split(",");
            var strHex = "#";
            let len = aColor.length;
            if (len > 3) {
                len = 3;
            }
            for (var i = 0; i < len; i++) {
                var hex = Number(aColor[i]).toString(16);
                if (hex.length === 1) {
                    hex = "0" + hex;
                }
                if (hex === "0") {
                    hex += hex;
                }
                strHex += hex;
            }
            if (strHex.length !== 7) {
                strHex = that;
            }
            return strHex.toUpperCase();
        } else if (HexReg.test(that)) {
            var aNum = that.replace(/#/, "").split("");
            if (aNum.length === 6) {
                return that.toUpperCase();
            } else if (aNum.length === 3) {
                var numHex = "#";
                for (var j = 0; j < aNum.length; j += 1) {
                    numHex += (aNum[j] + aNum[j]);
                }
                return numHex.toUpperCase();
            }
        } else if ($B.isPlainObjectFn(that)) {
            var hex = [
                that.r.toString(16),
                that.g.toString(16),
                that.b.toString(16)
            ];
            for (let i = 0; i < hex.length; i++) {
                let val = hex[i];
                if (val.length === 1) {
                    hex[i] = '0' + val;
                }
            }
            if (typeof that.a !== "undefined") {
                hex.push(that.a);
            }
            return '#' + hex.join('');
        } else {
            return that.toUpperCase();
        }
    },
    /**
     * 十六进制转rgba object对象
     * ***/
    hex2RgbObj: function (hexColor) {
        if (HexReg.test(hexColor)) {
            if (hexColor.length === 4) {
                var sColorNew = "#";
                for (var i = 1; i < 4; i += 1) {
                    sColorNew += hexColor.slice(i, i + 1).concat(hexColor.slice(i, i + 1));
                }
                hexColor = sColorNew;
            }
            //处理六位的颜色值
            var sColorChange = [];
            for (var j = 1; j < 7; j += 2) {
                sColorChange.push(parseInt("0x" + hexColor.slice(j, j + 2)));
            }
            return {
                r: sColorChange[0],
                g: sColorChange[1],
                b: sColorChange[2]
            };
        }
    },
    /**
  * 十六进制转rgba 字符串
  * ***/
    hex2Rgb: function (hexColor) {
        var rgbObj = this.hex2RgbObj(hexColor);
        if (rgbObj) {
            return "RGB(" + rgbObj.r + "," + rgbObj.g + "," + rgbObj.b + ")";
        }
    },
    rgbaStr2Obj: function (str) {
        let ret = /^rgb|RGB\((\d+),\s*(\d+),\s*(\d+),\s*([0,1]\.\d+)\)$/.exec(str);
        return {
            r: ret[1],
            g: ret[2],
            b: ret[3]
        };
    },
    getContrastColor: function (value) {
        if (!value) {
            return 'rgb(105, 118, 166)';
        }
        var rgb = value;
        if (typeof rgb === "string" && value.toLowerCase().indexOf("rgb") < 0) {
            rgb = this.hex2Rgb(value);
        }
        rgb.r = 255 - rgb.r;
        rgb.g = 255 - rgb.g;
        rgb.b = 255 - rgb.b;
        return ['rgb(', rgb.r, ',', rgb.g, ',', rgb.b, ')'].join('');
    },
    /**
     * 获取当前document的body，并且将其position声明为 relative
     * ***/
    getDomBody: function () {
        if (!$body) {
            $body = document.body.style.position = "relative";
        }
        return $body;
    },
    /****获取的当前浏览器的主机应用地址 *****/
    getHttpHost: function (ctxPath) {
        var proto = window.location.protocol;
        var host = proto + "//" + window.location.host;
        var ctx;
        if (!ctxPath && window.ctxPath) {
            ctx = window.ctxPath;
        } else if (ctxPath) {
            ctx = ctxPath;
        }
        if (ctx) {
            host = host + ctx;
        }
        return host;
    },
    /**
     * 用于优化递归实现的函数
     * ***/
    recursionFn: function (fn, isRemain) {
        var active = false;
        var accumulated = [];
        return function executeFn() {
            if (arguments.length === 1) {
                if (typeof arguments[0] === "string" && arguments[0] === "destroy") {
                    fn = undefined;
                    accumulated = undefined;
                    return;
                }
            }
            accumulated.push(arguments);//每次将参数传入. 例如, 1 100000
            if (!active) {
                active = true;
                while (accumulated.length) {
                    let args = accumulated.pop();
                    fn.apply(this, args);
                }
                active = false;
                if (!isRemain) {
                    fn = undefined;
                }
            }
        };
    },
    /***
     * args={
     *      url:,
     *      success:fn(data, status, xhr)
     *      error:fn(xhr, type, error),
     *      complete:fn()
     * }
     * ***/
    htmlLoad: function (args, targetEl) {
        var loadingEl;
        if (targetEl) {
            let el = $B.DomUtils.children(targetEl, ".k_loading_el");
            if (el.length === 0) {
                loadingEl = $B.getLoadingEl();
                $B.DomUtils.append(targetEl, loadingEl);
            }
            let p = $B.DomUtils.children(targetEl, ".k_req_error_p");
            $B.DomUtils.remove(p);
        }
        var defopt = {
            success: function (data, status, xhr) {
                if (targetEl) {
                    targetEl.innerHTML = data;
                }
            },
            error: function (xhr, type, error) {
                if (targetEl) {
                    targetEl.innerHTML = "<p class='k_req_error_p' style='text-align:center;'><i style='color:#D6D603' class='fa fa-attention'></i><span style='padding-left:10px'>" + xhr.statusText + "：" + xhr.status + "</span></p>";
                }
            },
            complete: function () {
                if (loadingEl) {
                    $B.removeLoading(loadingEl);
                }
            }
        };
        var opt;
        if (typeof args === "string") {
            opt = defopt;
            opt["url"] = args;
        } else {
            opt = $B.extendObjectFn({}, defopt, args);
        }
        $B.ajax(opt);
    },
    /**返回当前时间的格式化***/
    formateNow: function (format) {
        if (!format) {
            format = "yyyyMMddhhmmss";
        }
        return this.formateDate(new Date(), format);
    },
    /***格式化data***/
    formateDate: function (date, format) {
        return date.format(format);
    },
    /***生成随机数***/
    random: function (lower, upper) {
        if (!lower) {
            lower = 0;
        }
        if (!upper) {
            upper = 10000;
        }
        return Math.floor(Math.random() * (upper - lower)) + lower;
    },
    /***
     * 获取元素el的transform矩阵信息
     * ****/
    getMatrixArray: function (el) {
        var res;
        var matrix = el.style["transform"];
        if (matrix && matrix !== "none") {
            var values = matrix.split('(')[1].split(')')[0].split(',');
            res = [];
            for (var i = 0; i < values.length; i++) {
                res.push(parseFloat(values[i]));
            }
        }
        return res;
    },
    /**获取元素旋转后的位置偏移量**/
    getAnglePositionOffset: function (el) {
        var ofs = { fixTop: 0, fixLeft: 0 };
        var matrixArr = this.getMatrixArray(el);
        if (matrixArr) {
            var pos = $B.DomUtils.position(el);
            var angle = $B.getMatrixAngle(matrixArr);
            if (angle !== 0) {
                var clone = document.createElement("div");
                var style = el.getAttribute("style");
                clone.setAttribute("style", style);
                $B.DomUtils.css(clone, { "transform": "rotate(0deg)", "opacity": "0", "position": "absolute", "z-index": -111 });
                el.parentNode.append(clone);
                var clonePos = $B.DomUtils.position(clone);
                ofs.fixTop = clonePos.top - pos.top;
                ofs.fixLeft = -(pos.left - clonePos.left);
                el.parentNode.removeChild(clone);
            }
        }
        return ofs;
    },
    /**
    * 获取旋转的角度
    * matrix = css("transform")
    * **/
    getMatrixAngle: function (matrixArr) {
        var a = matrixArr[0];
        var b = matrixArr[1];
        var angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
        return angle;
    },
    /***
     * pos 是否在 el元素内
     * pos = {top:,left}
     * el :jq元素
     * ***/
    isInElement: function (pos, el, isRelative) {
        var ofs;
        if (isRelative) {
            ofs = el.position();
        } else {
            ofs = el.offset();
        }
        var w = el.outerWidth();
        var h = el.outerHeight();
        var matrix = $B.getMatrixArray(el);
        if (matrix) { //如果存在缩放               
            var rate = parseFloat(matrix[0]);
            h = h * rate;
            w = w * rate;
        }
        var endTop = ofs.top + h;
        var endLeft = ofs.left + w;
        if (pos.top >= ofs.top && pos.top <= endTop && pos.left >= ofs.left && pos.left <= endLeft) {
            return true;
        }
        return false;
    },
    /****
     * 对str字符串进行html符号替换，防止xss
     * *****/
    htmlEncode: function (str) {
        if (!str || typeof str.replace === "undefined") {
            return str;
        }
        var s = "";
        if (str.length === 0) {
            return "";
        }
        // s = str.replace(/%/g,"%25");
        s = str.replace(/</g, "&lt;");
        s = s.replace(/>/g, "&gt;");
        s = s.replace(/eval\((.*)\)/g, "");
        s = s.replace(/<.*script.*>/, "");
        /*双引号 单引号不替换
        s = s.replace(/\'/g,"&#39;");
        s = s.replace(/\"/g,"&quot;");*/
        return s;
    },
    /*****
     * 将html encode替换的符号，恢复
     * ******/
    htmlDecode: function (str) {
        if (typeof str.replace === "undefined") {
            return str;
        }
        var s = "";
        if (str.length === 0) {
            return "";
        }
        s = str.replace(/&amp;/g, "&");
        s = s.replace(/&lt;/g, "<");
        s = s.replace(/&gt;/g, ">");
        s = s.replace(/&#39;/g, "\'");
        s = s.replace(/&quot;/g, "\"");
        return s;
    },
    /**
     * 动态创建页面style样式
     * className：样式class名称
     * styleText：样式内容
     * ***/
    createHeaderStyle: function (className, styleText) {
        var header = document.getElementsByTagName('head')[0];
        this._appendHeaderStyle(header, className, styleText);
    },
    _appendHeaderStyle: function (header, className, styleText) {
        var element;
        var childs = header.children;
        for (var i = 0; i < childs.length; i++) {
            if (childs[i].className === className) {
                element = childs[i];
                break;
            }
        }
        if (element) {
            header.removeChild(element);
        }
        var style = document.createElement('style');
        style.type = "text/css";
        style.className = className;
        style.innerText = styleText;
        header.appendChild(style);
    },
    /***
     * 获取uuid
     * ***/
    getUUID: function () {
        return this.generateDateUUID();
    },
    getIdIdx: function () {
        if (!window["_$_idx_"]) {
            window["_$_idx_"] = 1;
        } else {
            window["_$_idx_"]++;
        }
        return window["_$_idx_"];
    },
    /**
    * 生成短位数的uuid
    * **/
    getShortID: function () {
        var prex = (new Date()).format("hhmmssSS") + this.getIdIdx();
        var str = this.generateMixed(5);
        return "k_" + prex + str;
    },
    /**
     * 生成uuid
     * fmt：格式yyyyMMddhhmmssSSS,
     * count
     * **/
    generateDateUUID: function (fmt, count) {
        var c = count ? count : 5;
        var formt = fmt ? fmt : "yyMMddhhmmssSS";
        var prex = (new Date()).format(formt) + this.getIdIdx();
        return "k_" + prex + this.generateMixed(c);
    },
    /***产生混合随机数
     *@param n 位数 默认6
     ***/
    generateMixed: function (n) {
        var _n = n ? n : 6;
        var res = [];
        for (var i = 0; i < _n; i++) {
            var id = Math.ceil(Math.random() * 35);
            res.push(CHARSArr[id]);
        }
        return res.join("");
    },
    /**是否是url**/
    isUrl: function (str) {
        if (typeof str !== 'string') {
            return false;
        }
        if (str && str.indexOf("/") < 0) {
            return false;
        }
        return /^((http(s)?|ftp):\/\/)?([\w-]+\.)*[\w-]+(\/[\w-.\/?%&=]*)?(:\d+)?/.test(str);
    },
    /**
     * css样式对象转字符串格式
     * ***/
    cssObj2string: function (cssObj) {
        var res = [];
        var keys = Object.keys(cssObj);
        var key;
        for (var i = 0; i < keys.length; i++) {
            key = keys[i];
            res.push(key + ":" + cssObj[key]);
        }
        return res.join(";");
    },
    /****
     * style字符串转css对象
     * ***/
    style2cssObj: function (style) {
        if (typeof style !== "string") {
            style = $B.DomUtils.attribute(style, "style");
        }
        var res = {};
        if (!style || style === "") {
            return res;
        }
        var tmp = style.split(";");
        var oneArr;
        for (var i = 0; i < tmp.length; i++) {
            if (tmp[i] !== "") {
                oneArr = tmp[i].split(":");
                res[$B.trimFn(oneArr[0])] = $B.trimFn(oneArr[1]);
            }
        }
        return res;
    },
    /***
     * 将参数object对象，转为字符串形式
     * dataObj：{}数据对象
     * isMakeRandom：是否形成一个随机参数
     * encodeUrl：是否进行encodeURIComponent
     * ***/
    formatUrlParams: function (dataObj, isMakeRandom, encodeUrl) {
        var arr = [];
        var rnd, encode;
        rnd = typeof isMakeRandom !== "undefined" ? isMakeRandom : false;
        encode = typeof encodeUrl !== "undefined" ? encodeUrl : true;
        let keys = Object.keys(dataObj);
        for (let i = 0; i < keys.length; i++) {
            if (encode) {
                arr.push(encodeURIComponent(keys[i]) + "=" + encodeURIComponent(dataObj[keys[i]]));
            } else {
                arr.push(encodeURIComponent(keys[i]) + "=" + dataObj[keys[i]]);
            }
        }
        if (rnd) {
            arr.push(("_rmd=" + Math.random()).replace(".", ""));
        }
        return arr.join("&");
    },
    isNotEmpty: function (v) {
        return v !== null && typeof v !== 'undefiend' && v !== "";
    },
    /***
    * 写cookie
    * ***/
    writeCookie: function (name, value, expiredays) {
        if (!this.isNotEmpty(expiredays)) {
            expiredays = 1;
        }
        try {
            var exdate = new Date();
            exdate.setDate(exdate.getDate() + expiredays);
            document.cookie = name + "=" + window.escape(value) + ";expires=" + exdate.toGMTString();
        } catch (ex) {
            console.log("write cookied err ", ex);
        }
    },
    /**
     * 读取cookie
     * ***/
    getCookie: function (c_name) {
        if (document.cookie.length > 0) {
            var c_start = document.cookie.indexOf(c_name + "=");
            if (c_start !== -1) {
                c_start = c_start + c_name.length + 1;
                var c_end = document.cookie.indexOf(";", c_start);
                if (c_end === -1) {
                    c_end = document.cookie.length;
                }
                return window.unescape(document.cookie.substring(c_start, c_end));
            }
        }
        return "";
    },
    /**
     * 循环数组
     * ***/
    foreach: function (arr, fn) {
        for (let i = 0; i < arr.length; i++) {
            fn(arr[i]);
        }
    },
    /***
     * 替换换行，回车
     * ***/
    replaceSpaceChar: function (str) {
        var string = str;
        try {
            string = string.replace(/\r\n/g, "");
            string = string.replace(/\n/g, "");
            string = string.replace(/\s+/g, "");
        } catch (e) {
        }
        return string;
    },
    /**获取滚动条宽度**/
    getScrollWidth: function () {
        var key = '_CURRENT_SCROLL_SIZE_';
        if (typeof window[key] !== "undefined") {
            return window[key];
        }
        var noScroll, scroll, oDiv = document.createElement("DIV");
        oDiv.style.cssText = "position:absolute; top:-1000px; width:100px; height:100px; overflow:hidden;";
        noScroll = document.body.appendChild(oDiv).clientWidth;
        oDiv.style.overflowY = "scroll";
        scroll = oDiv.clientWidth;
        document.body.removeChild(oDiv);
        window[key] = noScroll - scroll;
        return window[key];
    },
    vueForm: function (el, bean, formCtls, opts) {
        if (typeof Vue !== "function") {
            console.log("please import vue!");
            alert("please import vue!");
            return;
        }
        var verifyOnChange = opts.verifyOnChange;
        opts.verifyOnChange = false;
        let elId;
        if (typeof el === "string") {
            elId = el.replace("#", "");
            el = document.getElementById(elId);
        } else {
            elId = el.id;
            if(!elId){
                elId = this.getUUID();
                $B.DomUtils.attribute(el, { id: elId });
            }          
        }
        if (!$B.isPlainObjectFn(opts.verify)) {
            opts.verify = {};
        }
        if (!$B.isPlainObjectFn(bean)) {
            bean = {};
        }
        if (!$B.isPlainObjectFn(formCtls)) {
            formCtls = {};
        }
        let formData = {};
        let watch = {};
        let diyCtlArray = [];
        let diyDataBean = {};
        let lableIdMap = {};
        let mouseTipEls = [];
        this._loopFormEl(el, (el) => {
            if (!$B.DomUtils.attribute(el, "not_bind")) {
                let tagName = el.tagName;
                let id = el.id;
                let formName = id;
                let ctlOpt = formCtls[id];               
                if (tagName === "INPUT") {
                    if (ctlOpt) {//如果是自定义的控件
                        diyCtlArray.push({
                            id: id,
                            ctlOpt: ctlOpt
                        });
                        if (ctlOpt.ctl === "Combox") {
                            formData[id] = [];
                        } else if (ctlOpt.ctl === "Calendar") {
                            formData[id] = "";
                        } else if (ctlOpt.ctl === "switchCtl") {
                            if (typeof bean[id] !== "undefined") {
                                formData[id] = bean[id];
                                el.value = bean[id];
                            } else {
                                if (el.value !== "1") {
                                    el.value = 0;
                                    bean[id] = 0;
                                } else if (typeof bean[id] === "undefined") {
                                    bean[id] = el.value;
                                }
                                formData[id] = bean[id];
                            }
                        } else if (ctlOpt.ctl === "NUMInputCtl") {
                            $B.DomUtils.attribute(el, { "v-model": id });
                            let $pan = $B.Dom.after(el, "<span class='k_fnumber_wrap'></span>");
                            el.parentNode.removeChild(el);
                            $B.Dom.append($pan, el);
                            if (typeof bean[id] !== "undefined") {
                                formData[id] = bean[id];
                                el.value = bean[id];
                            } else {
                                formData[id] = 0;
                                el.value = 0;
                            }
                        }
                        diyDataBean[id] = bean[id];
                        delete bean[id];
                    } else {
                        let type = el.type;
                        if (type === "text" || type === "password" || type === "hidden") {
                            if (type === "hidden" && formName.indexOf("old_") === 0) {
                                let fname = formName.replace("old_", "");
                                el.value = bean[fname] ? bean[fname] : "";
                            }
                            formData[id] = el.value;
                            $B.DomUtils.attribute(el, { "v-model": id });
                        } else if (type === "radio") {
                            if (typeof formData[el.name] === "undefined") {
                                formData[el.name] = el.value;
                            }
                            if (el.checked) {
                                formData[el.name] = el.value;
                            }
                            $B.DomUtils.attribute(el, { "v-model": el.name });
                            formName = el.name;
                            if (!lableIdMap[formName]) {
                                lableIdMap[formName] = [];
                            }
                            lableIdMap[formName].push(el);
                        } else if (type === "checkbox") {
                            if (!formData[el.name]) {
                                formData[el.name] = [];
                                if (bean[el.name] && !Array.isArray(bean[el.name])) {
                                    bean[el.name] = bean[el.name].split(";");
                                }
                            }
                            if (el.checked) {
                                formData[el.name].push(el.value);
                            }
                            $B.DomUtils.attribute(el, { "v-model": el.name });
                            formName = el.name;
                            if (!lableIdMap[formName]) {
                                lableIdMap[formName] = [];
                            }
                            lableIdMap[formName].push(el);
                        }
                    }
                } else if (tagName === "TEXTAREA") {
                    formData[id] = el.innerText ? el.innerText : "";
                    $B.DomUtils.attribute(el, { "v-model": id });
                } else if (tagName === "SELECT") {
                    let child = el.children;
                    formData[id] = "";
                    for (let i = 0; i < child.length; i++) {
                        if (child[i].selected) {
                            formData[id] = child[i].value;
                            break;
                        }
                    }
                    $B.DomUtils.attribute(el, { "v-model": id });
                } else if (tagName === "UL") {//树控件
                    if (ctlOpt) {//如果是自定义的控件
                        if (ctlOpt.ctl === "Tree") {
                            formData[id] = undefined;
                        }
                        diyDataBean[id] = bean[id];
                        delete bean[id];
                        diyCtlArray.push({
                            id: id,
                            ctlOpt: ctlOpt
                        });
                    }
                }
                watch[formName] = this._getWatchFn(formName, opts);
                if($B.Dom.attr(el,"tip_lbl")){                   
                    if(!el.id){
                        el.id = $B.getUUID();
                    }
                    mouseTipEls.push(el.id);
                }
            }
        });
        $B.extendObjectFn(formData, bean);
        let lblKeys = Object.keys(lableIdMap);
        for (let i = 0; i < lblKeys.length; i++) {
            let lblName = lblKeys[i];
            let lsEls = lableIdMap[lblName];
            let itEl = lsEls[lsEls.length - 1];
            let pEl = itEl.parentNode;
            if (pEl.tagName === "LABEL") {
                $B.DomUtils.attribute(pEl, { id: "k_lbl_" + lblName });
            } else {
                $B.DomUtils.attribute(itEl, { id: "k_lbl_" + lblName });
            }
        }        
        let vueObj = new Vue({
            el: "#" + elId,
            data: formData,
            watch: watch,
            mounted: function () {
            },
            updated: function () {
                if (opts.onUpateFn) {
                    setTimeout(() => {
                        opts.onUpateFn.call(this);
                    }, 1);
                }
            }
        });
        var onValueChange = function (name, newVal, oldVal) {
            if ($B.isPlainObjectFn(newVal)) {
                newVal = $B.cloneObjectFn(newVal);
            }
            let skipFieldMvm = "_$skip_" + name;
            vueObj[skipFieldMvm] = name;
            formData[name] = newVal;
            setTimeout(() => {
                delete vueObj[skipFieldMvm];
            }, 1);
        };
        //创建自定义控件,控件必须实现onChange，setValue
        let diyCtlMap = {};
        vueObj["_$diyCtlMap"] = diyCtlMap;
        let formEl = document.getElementById(elId);
        opts.$form = formEl;
        for (let i = 0; i < diyCtlArray.length; i++) {
            let ctlEl = $B.DomUtils.findbyId(formEl, diyCtlArray[i].id);
            let ctlOpt = diyCtlArray[i].ctlOpt;
            let ctlName = ctlOpt.ctl;
            if ($B[ctlName]) {
                let ctlObj;
                ctlOpt.opts.onChange = onValueChange;
                if (ctlName.indexOf("Ctl") > 0) {
                    ctlObj = $B[ctlName](ctlEl, ctlOpt.opts);
                } else {
                    ctlObj = new $B[ctlName](ctlEl, ctlOpt.opts);
                }
                diyCtlMap[diyCtlArray[i].id] = ctlObj;
                //修改值以触发自定义控件的ui绑定
                if (diyDataBean[diyCtlArray[i].id]) {
                    formData[diyCtlArray[i].id] = diyDataBean[diyCtlArray[i].id];
                    delete diyDataBean[diyCtlArray[i].id];
                }
            } else {
                console.log("[" + ctlName + "] 没有找到！");
            }
        }
        formData["toJSON"] = function (array2str) {
            let keys = Object.keys(this);
            let res = {};
            for (let i = 0; i < keys.length; i++) {
                let key = keys[i];
                if (typeof this[key] !== "function" && key !== "$form") {
                    if (Array.isArray(this[key])) {
                        if (array2str) {
                            res[key] = $B._arr2str(this[key]);
                        } else {
                            res[key] = [...this[key]];
                        }
                    } else {
                        res[key] = this[key];
                    }
                }
            }
            return res;
        };
        formData["toJSONStr"] = function (array2str) {
            return JSON.stringify(this.toJSON(array2str));
        };
        formData["toDestroy"] = function () {
            opts.verify = undefined;
            let ctls = Object.values(diyCtlMap);
            for (let i = 0; i < ctls.length; i++) {
                ctls[i].destroy();
            }
            vueObj.$destroy();
            vueObj["_$diyCtlMap"] = undefined;
            formData["toDestroy"] = undefined;
            formData["toJSON"] = undefined;
            formData["toJSONStr"] = undefined;
            formData["toVerify"] = undefined;
            formData["$form"] = undefined;
            opts.$form = undefined;
            formData.__ob__ = undefined;
            formData = undefined;
            diyCtlMap = undefined;
            opts = undefined;
            formEl = undefined;
        };
        formData["toVerify"] = function () {
            if ($B.isEmptyObjectFn(opts.verify)) {
                return true;
            }
            let formKeys = Object.keys(opts.verify);
            let isPast = true;
            for (let i = 0; i < formKeys.length; i++) {
                let formName = formKeys[i];
                let value = formData[formName];
                if (typeof value === "undefined") {
                    value = "";
                }
                let vrfCfg = opts.verify[formName];
                let r = $B._exeVerify(formName, value, vrfCfg, formEl);
                if (!r) {
                    isPast = r;
                }
            }
            return isPast;

        };
        setTimeout(() => {
            opts.verifyOnChange = verifyOnChange;
            //鼠标提示支持
            for(let i =0 ; i < mouseTipEls.length ;i++){
                let id = mouseTipEls[i];
                let el = $B.DomUtils.findbyId(formEl,id);
                $B.mouseTip(el, $B.Dom.attr(el,"tip_lbl"), undefined, "#9090C9");
            }
        }, 20);
        this.bindInputClear(formEl, (elName) => {
            if (formData[elName]) {
                formData[elName] = "";
                return true;
            }
            console.log("formData is undefined！");
            return false;
        });
        formData.$form = formEl;      
        return formData;
    },
    /**
 * 创建开关控件
 * @param  el
 * @param  opts {
            trueText:"是",
            falseText:"否",                    
            onChange:(value)=>{
                console.log(value);
            }
        }
    */
    switchCtl: function (el, opts) {
        let id;
        if (typeof el === "string") {
            id = el.replace("#", "");
            el = document.getElementById(id);
        } else {
            let id = $B.DomUtils.attribute(el, "id");
            if (!id) {
                id = "sw_" + $B.getShortID();
                $B.DomUtils.attribute(el, { "id": id });
            }
        }
        let chkCls = "k_switch_core_checked";
        if (el.value === "" || el.value !== "1") {
            el.value = "0";
            chkCls = "";
        }
        let $wrap = $B.DomUtils.createEl("<span class='k_switch_wrap'><span class='k_switch_left_label'></span><span class='k_switch_core " + chkCls + "'></span><span class='k_switch_right_label'></span></span>");
        if (opts.trueText) {
            $wrap.firstChild.innerText = opts.trueText;
            $B.DomUtils.addClass($wrap.firstChild, "k_switch_l_padding");
        }
        if (opts.falseText) {
            $wrap.lastChild.innerText = opts.falseText;
            $B.DomUtils.addClass($wrap.lastChild, "k_switch_r_padding");
        }
        if (chkCls === "") {
            $B.DomUtils.addClass($wrap.lastChild, "k_switch_label_checked");
        } else {
            $B.DomUtils.addClass($wrap.firstChild, "k_switch_label_checked");
        }
        $B.DomUtils.after(el, $wrap);
        $B.DomUtils.remove(el);
        $B.DomUtils.append($wrap, el);
        $B.DomUtils.click($wrap, (e) => {
            let $el = e.target;
            while ($el) {
                if ($B.DomUtils.hasClass($el, "k_switch_wrap")) {
                    break;
                }
                $el = $el.parentNode;
            }
            let childs = $B.DomUtils.children($el, "span");
            let oldClazz = [];
            for (let i = 0; i < childs.length; i++) {
                oldClazz.push($B.DomUtils.attribute(childs[i], "class"));
            }
            let $c = $B.DomUtils.children($el, ".k_switch_core")[0];
            let oldVal = $el.lastChild.value;
            if ($B.DomUtils.hasClass($c, "k_switch_core_checked")) {
                $B.DomUtils.removeClass($c, "k_switch_core_checked");
                $el.lastChild.value = "0";
                $B.DomUtils.removeClass($c.previousSibling, "k_switch_label_checked");
                $B.DomUtils.addClass($c.nextSibling, "k_switch_label_checked");
            } else {
                $B.DomUtils.addClass($c, "k_switch_core_checked");
                $el.lastChild.value = "1";
                $B.DomUtils.addClass($c.previousSibling, "k_switch_label_checked");
                $B.DomUtils.removeClass($c.nextSibling, "k_switch_label_checked");
            }
            if (opts.onChange) {
                opts.onChange.call($el, $el.lastChild.id, $el.lastChild.value, oldVal, oldClazz);
            }
        });
        if (!opts.notReturn) {
            return {
                setValue: function (val, triggerChange) {
                    let isChecked = true;
                    if (typeof val === "boolean") {
                        isChecked = val;
                    } else if (typeof val === "number") {
                        isChecked = val === 1;
                    } else {
                        isChecked = val === "1";
                    }
                    let $c = $B.DomUtils.children($wrap, ".k_switch_core")[0];
                    if (isChecked) {
                        $B.DomUtils.addClass($c, "k_switch_core_checked");
                        $wrap.lastChild.value = "1";
                        $B.DomUtils.addClass($c.previousSibling, "k_switch_label_checked");
                        $B.DomUtils.removeClass($c.nextSibling, "k_switch_label_checked");
                    } else {
                        $B.DomUtils.removeClass($c, "k_switch_core_checked");
                        $wrap.lastChild.value = "0";
                        $B.DomUtils.removeClass($c.previousSibling, "k_switch_label_checked");
                        $B.DomUtils.addClass($c.nextSibling, "k_switch_label_checked");
                    }
                },
                destroy: function () {
                    $B.DomUtils.remove($wrap);
                    opts.onChange = undefined;
                    opts = undefined;
                    this.setValue = undefined;
                    this.destroy = undefined;
                }
            };
        }
    },
    NUMInputCtl: function (el, opts) {       
        if (!$B.Dom.hasClass(el, "k_number_input")) {
            if (!$B.Dom.hasClass(el.parentNode, "k_fnumber_wrap")) {
                let $span = $B.Dom.after(el, "<span class='k_fnumber_wrap'></span>");
                el.parentNode.removeChild(el);
                $B.Dom.append($span, el);
            }
            $B.Dom.addClass(el, "k_number_input");
            let $prt = el.parentNode;
            let btn = $B.Dom.append($prt, "<span style='position:absolute;top:0px;right:2px;display:inline-block;line-height: 12px;' class='up-dir'><i class='fa fa-up-dir'></i></span>");
            let btn1 = $B.Dom.append($prt, "<span style='position:absolute;bottom:0px;right:2px;display:inline-block;line-height: 12px;' class='down-dir'><i class='fa fa-down-dir'></i></span>");
            let clickFN = (e) => {
                let step = 1;
                if (opts.step) {
                    step = parseFloat(opts.step);
                }
                let catpurer = e.catpurer;
                let oldVal = $B.trimFn(el.value);
                if ($B.config.verify.number.reg.test(oldVal)) {
                    oldVal = parseFloat(oldVal);
                } else {
                    oldVal = 0;
                }
                let newVal;
                if ($B.Dom.hasClass(catpurer, "up-dir")) {
                    newVal = oldVal.add(step);
                } else {
                    newVal = oldVal.sub(step);
                }
                if(typeof opts.min !== "undefined"){
                    if(newVal < opts.min){
                        return false;
                    }
                }
                if(typeof opts.max !== "undefined"){
                    if(newVal > opts.max){
                        return false;
                    }
                }
                el.value = newVal;               
                opts.onChange(el.id, newVal, oldVal);                
            };
            $B.Dom.click(btn, clickFN);
            $B.Dom.click(btn1, clickFN);
        }

    },
    _getWatchFn: function (formName, opts) {
        return function (newVal, oldVal) {
            let diyCtlMap = this._$diyCtlMap;
            let diyCtlINS = diyCtlMap[formName];
            if (diyCtlINS) {
                let skipFieldMvm = "_$skip_" + formName;
                if (!this[skipFieldMvm]) {
                    if (diyCtlINS.setValue) {
                        let argsVal = newVal;
                        if (Array.isArray(newVal) || $B.isPlainObjectFn(newVal)) {
                            argsVal = $B.cloneObjectFn(newVal);
                        }
                        diyCtlINS.setValue(argsVal, false);
                    } else {
                        console.log("the ctl not impl setValue!");
                    }
                }
            }
            //值发生变化，可触发验证
            let isError = false;
            if (opts.verifyOnChange) {
                let verifyArgs = opts.verify[formName];
                if (verifyArgs) {
                    isError = !$B._exeVerify(formName, newVal, verifyArgs, opts.$form);
                }
            }
            if (opts.onChange) {
                opts.onChange(formName, newVal, oldVal,isError);
            }
        };
    },
    /**
     * 验证一个表单项目
     * ***/
    _exeVerify: function (formName, newVal, verifyArgs, $form) {
        //console.log("exe verify ",newVal,formName,verifyArgs);
        let ret = [], res;
        if (Array.isArray(verifyArgs)) {
            for (let i = 0; i < verifyArgs.length; i++) {
                if (typeof verifyArgs[i] === "function") {
                    res = verifyArgs[i](formName, newVal, $form);
                } else {
                    res = $B._verify(verifyArgs[i], newVal);
                }
                if (res) {
                    ret.push(res);
                }
            }
        } else {
            if (typeof verifyArgs === "function") {
                res = verifyArgs(formName, newVal, $form);
            } else {
                res = $B._verify(verifyArgs, newVal);
            }
            if (res) {
                ret.push(res);
            }
        }
        let el = $B.DomUtils.findbyId($form, formName);
        if (!el) {
            el = $B.DomUtils.findbyId($form, "k_lbl_" + formName);
        }
        if (el) {
            let parentEl = el.parentNode;  
            if($B.Dom.css(parentEl,"display") === "inline-block" || $B.Dom.hasClass(parentEl.parentNode,"k_form_it_wrap")){
                parentEl = parentEl.parentNode;
            }
            let lplPrt = parentEl;
            let $row,$col,$item;
            let i = 0 ;
            while(i < 10 && lplPrt){
                if(lplPrt.nodeName === "BODY"){
                    break;
                }
                if($B.Dom.hasClass(lplPrt,"k_flow_form_item")){
                    $item = lplPrt;
                }
                if($B.Dom.hasClass(lplPrt,"k_flex_form_col")){
                    $col = lplPrt;
                }
                if($B.Dom.hasClass(lplPrt,"k_flex_form_row")){
                    $row = lplPrt;
                    break;
                }
                lplPrt = lplPrt.parentNode;
                i++;
            }           
            let errEl = $B.DomUtils.children(parentEl, ".k_verify_err_el");
            if (errEl.length == 0) {
                errEl = $B.DomUtils.append(parentEl, "<div style='display:none;position:relative;' class='k_verify_err_el'></div>");
            } else {
                errEl = errEl[0];
            }
            if (ret.length > 0) {
                let display = "inline-block";
                ret = $B.uniqueArray(ret);
                let errMsg = ret.join("; ");
                let len = $B.getCharWidth(errMsg) + 20;
                errEl.style.display = "none";
                errEl.style.width = len +"px";
                 //计算合适的位置
                if($row){ //flex布局表单                   
                    if(!$col.nextSibling && !$item.nextSibling){
                        let rwidth = $B.Dom.width($row);
                        let preWidth = 0;
                        while($col){
                            preWidth = preWidth + $B.Dom.outerWidth($col);
                            $col = $col.previousSibling;
                        }                     
                        let alvWidth = rwidth - preWidth;
                        if(alvWidth < len){
                            display = "block";
                            errEl.style.width = (alvWidth - 2) + "px";
                        }
                    }else{
                        let colWidth = $B.Dom.width($item) -2;
                        errEl.style.width = colWidth + "px";
                        display = "block";
                    }
                }           
                if ($B.DomUtils.hasClass(el, "k_combox_wrap")) {
                    $B.DomUtils.addClass(el.firstChild, "k_input_value_err");
                } else {
                    $B.DomUtils.addClass(el, "k_input_value_err");
                }
                errEl.innerText = errMsg;
                if(display === "inline-block"){
                    errEl.style.paddingLeft = "2px"; 
                }else{
                    errEl.style.paddingLeft = "0px"; 
                }
                errEl.style.display = display;
            } else {
                if ($B.DomUtils.hasClass(el, "k_combox_wrap")) {
                    $B.DomUtils.removeClass(el.firstChild, "k_input_value_err");
                } else {
                    $B.DomUtils.removeClass(el, "k_input_value_err");
                }
                errEl.style.display = "none";
            }
        }
        return ret.length === 0;
    },
    _verify: function (rule, val) {
        if ($B.config) {
            if (typeof rule === "string") {//内置的规则
                return $B._defaultVerify(val, rule);
            } else if ($B.isPlainObjectFn(rule)) {
                if (rule.rule) {//内置的规则
                    let ruleName = rule.rule;
                    let label = rule.label;
                    return $B._defaultVerify(val, ruleName, label, rule);
                } else if (rule.reg) {//自定义正则表达式                    
                    if (val !== "" && !rule.reg.test(val)) {
                        let label = $B.config.verify.regLabel;
                        if (rule.label) {
                            label = rule.label;
                        }
                        return label;
                    }
                }
            }
        }
    },
    _defaultVerify: function (val, ruleName, label, rule) {
        let vcfg = $B.config.verify;
        let cfg = vcfg[ruleName];
        if (cfg) {
            if (!label) {
                label = cfg.label;
            }
            if ("remote" === ruleName) {//远程验证
                console.log("远程验证 尚未实现！");
            } else if ("require" === ruleName) {
                if (Array.isArray(val)) {
                    if (val.length === 0) {
                        return label;
                    }
                } else {
                    val = $B.trimFn(val);
                    if (val === "") {
                        return label;
                    }
                }
            } else if ("range" === ruleName) {
                if (val !== "") {
                    if (!vcfg.number.reg.test(val)) {
                        return vcfg.number.label;
                    }
                    let min = rule.min;
                    let max = rule.max;
                    let number = parseFloat(val);
                    if (number < min || number > max) {
                        return label.replace("{1}", min).replace("{2}", max);
                    }
                }
            } else if ("minlength" === ruleName) {
                if (val !== "" && val.length < rule.len) {
                    return label.replace("{1}", rule.len);
                }
            } else if ("maxlength" === ruleName) {
                if (val !== "" && val.length > rule.len) {
                    return label.replace("{1}", rule.len);
                }
            } else {
                if (val !== "" && !cfg.reg.test(val)) {
                    return label;
                }
            }
        }
    },
    _arr2str: function (arr) {
        let tmp = [];
        for (let i = 0; i < arr.length; i++) {
            if (Array.isArray(arr[i])) {
                tmp.push(this._arr2str(arr[i]));
            } else {
                tmp.push(arr[i]);
            }
        }
        return tmp.join(";");
    },
    _loopFormEl: function (el, onLoopFn) {
        onLoopFn(el);
        var children = el.children;
        for (let i = 0; i < children.length; i++) {
            let child = children[i];
            this._loopFormEl(child, onLoopFn);
        }
    },
    uniqueArray: function (arr) {
        return Array.from(new Set(arr));
    },
    /**
     * 生成16位的对称加密key
     * **/
    AESGenKey: function (length = 16) {
        let random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        let str = "";
        for (let i = 0; i < length; i++) {
            str = str + random.charAt(Math.random() * random.length)
        }
        return str;
    },
    /**
     * des加密 依赖于encrypt-min.js
     * ***/
    AESEncrypt: function (plaintext, key) {
        if (typeof window["CryptoJS"] === "undefined") {
            console.log("没有加载 》》 CryptoJS");
            return message;
        }
        if (plaintext instanceof Object) {
            plaintext = JSON.stringify(plaintext)
        }
        let encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(plaintext),
            CryptoJS.enc.Utf8.parse(key),
            { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
        return encrypted.toString();
    },
    /**
     * des解密
     * **/
    AESDecrypt: function (ciphertext, key) {
        if (typeof window["CryptoJS"] === "undefined") {
            console.log("没有加载 》》 CryptoJS");
            return message;
        }
        let decrypt = CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse(key),
            { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
        let decString = CryptoJS.enc.Utf8.stringify(decrypt).toString();
        if (decString.charAt(0) === "{" || decString.charAt(0) === "[") {
            decString = JSON.parse(decString);
        }
        return decString;
    },
    //RSA 位数，这里要跟后端对应
    RSAGenKeys: function (bits = 1024) {
        if (typeof window["JSEncrypt"] === "undefined") {
            console.log("没有加载 JSEncrypt");
            return message;
        }
        let genKeyPair = {};
        if (!this.genKeyPairGener) {
            let genKeyPairGen = new JSEncrypt({ default_key_size: bits });
            this.genKeyPairGener = genKeyPairGen;
        }
        //获取私钥
        genKeyPair.privateKey = this.genKeyPairGener.getPrivateKey();//.replace("----BEGIN RSA PRIVATE KEY-----\n","").replace("\n-----END RSA PRIVATE KEY-----","");
        //获取公钥
        genKeyPair.publicKey = this.genKeyPairGener.getPublicKey();//.replace("-----BEGIN PUBLIC KEY-----\n","").replace("\n-----END PUBLIC KEY-----","");       
        return genKeyPair;
    },
    //公钥加密
    RSAEncrypt: function (plaintext, publicKey) {
        if (!this.genKeyPairGener) {
            alert("please invoke RSAGenKeys !");
            return;
        }
        if (plaintext instanceof Object) {
            plaintext = JSON.stringify(plaintext)
        }
        publicKey && this.genKeyPairGener.setPublicKey(publicKey);
        return this.genKeyPairGener.encryptLong(plaintext);
    },
    //私钥解密
    RSADecrypt: function (ciphertext, privateKey) {
        if (!this.genKeyPairGener) {
            alert("please invoke RSAGenKeys !");
            return;
        }
        privateKey && this.genKeyPairGener.setPrivateKey(privateKey);
        let decString = this.genKeyPairGener.decryptLong(ciphertext);
        if (decString.charAt(0) === "{" || decString.charAt(0) === "[") {
            decString = JSON.parse(decString);
        }
        return decString;
    },
    bindInputClear: function (form, onClearFn) {
        if (typeof form === "string") {
            form = document.getElementById(form.replace("#", ""));
        }
        let inputs = $B.DomUtils.findByTagName(form, "input[type=text]");
        let pws = $B.DomUtils.findByTagName(form, "input[type=password]");
        let textArea = $B.DomUtils.findByTagName(form, "textarea");
        if (!window["_inputClearEvs"]) {
            window["_inputClearEvs"] = {
                mouseenter: function (e) {
                    let $clearBtn = $B.DomUtils.findbyId(document.body, "#k_global_clear_btn");
                    if (!$clearBtn) {
                        $clearBtn = $B.DomUtils.createEl("<div id='k_global_clear_btn' style='position:absolute;display:none;z-index:2147483647;width:8px;height:14px;cursor:pointer;'><i style='color:#ccc;' class='fa  fa-cancel-1'></i></div>");
                        $B.DomUtils.append(document.body, $clearBtn);
                        $B.DomUtils.click($clearBtn, function () {
                            let el = this._el;
                            this.style.display = "none";
                            if (el) {
                                el.value = "";
                                this._el = undefined;
                                if (el.onClearFn) {
                                    if (!el.onClearFn(el.id)) {
                                        el.onClearFn = undefined;
                                    }
                                }
                                el.focus();
                            }
                        });
                    }
                    if (this.value !== "") {
                        let ofs = $B.DomUtils.offset(this);
                        let w = $B.DomUtils.outerWidth(this);
                        let h = $B.DomUtils.outerHeight(this);
                        ofs.top = ofs.top + (h - 20) / 2;
                        ofs.left = ofs.left + w - 10;
                        $B.DomUtils.css($clearBtn, ofs);
                        $clearBtn.style.display = "block";
                        $clearBtn._el = this;
                    }
                },
                mouseleave: function (e) {
                    let x = e.pageX;
                    let y = e.pageY;
                    let min = $B.DomUtils.offset(this);
                    let w = $B.DomUtils.outerWidth(this);
                    let h = $B.DomUtils.outerHeight(this);
                    let max = {
                        top: min.top + h,
                        left: min.left + w
                    };
                    if (!(x > min.left && x < max.left && y > min.top && y < max.top)) {
                        let $clearBtn = $B.DomUtils.findbyId(document.body, "#k_global_clear_btn");
                        if ($clearBtn) {
                            $clearBtn._el = undefined;
                            $clearBtn.style.display = "none";
                        }
                    }
                }
            };
        }
        Array.prototype.push.apply(inputs, pws);
        Array.prototype.push.apply(inputs, textArea);
        for (let i = 0, len = inputs.length; i < len; i++) {
            if (!$B.DomUtils.attribute(inputs[i], "readonly") && !$B.DomUtils.attribute(inputs[i], "disabled")) {
                let $in = inputs[i];
                if(!$B.Dom.getData($in,"clear_ev")){
                    let canBind = !$B.DomUtils.hasClass($in, "k_calendar_input") && !$B.DomUtils.hasClass($in, "k_combox_input")
                    &&  !$B.DomUtils.hasClass($in, "k_number_input");
                    if (canBind) {
                        $in.onClearFn = onClearFn;
                        $B.DomUtils.addClass($in, "k_box_size");
                        $B.DomUtils.css($in, { "padding-right": "10px" });
                        $B.DomUtils.bind($in, window["_inputClearEvs"]);
                        $B.DomUtils.setData($in,  "clear_ev", true );
                    }
                }             
            }
        }
    },
    /**
     * $wap: iframe容器
     * htmlEl: iframe内部的html
     * style:写入的样式
     * ***/
    createTextIfr: function ($wap, htmlEl, style, ifrCss) {
        let $ifr = $B.DomUtils.createEl('<iframe class="text_ifr" frameborder="0" style="width:100%;height:100%;" scrolling="no"></iframe>');
        if (ifrCss) {
            $B.DomUtils.css($ifr, ifrCss);
        }
        $B.DomUtils.append($wap, $ifr);
        var $body = $ifr.contentWindow.document.body;
        var $head = $ifr.contentWindow.document.head;
        $B.DomUtils.append($body, htmlEl);

        this._appendHeaderStyle($head, "base", "*{padding: 0;margin: 0;font-size: 14px;line-height: 1.5em;font-family: 'Microsoft Yahei', Helvetica, Arial, sans-serif;color: #1A242C;}"
            + "html,body{width:100%;height:100%}  *:focus {outline: none} textarea{padding: 2px 2px;text-align: left;border: 1px solid #ccc;} button{background: none;white-space: nowrap;border: 1px solid rgb(196, 224, 255);border-radius: 2px;padding: 1px 3px;line-height: 1.5em;cursor: pointer;font-size:13px;}"
            + "input::-webkit-input-placeholder，input::-moz-placeholder，input:-moz-placeholder，input:-ms-input-placeholder{color:#A9A9A9;}"
            + "input[type=text]:focus , input[type=password]:focus, textarea:focus{border-color: #409eff;} table{border-collapse: separate;border-spacing: 0;table-layout: fixed;} table td{padding:5px 2px;}"
            + "input.k_input_value_err,textarea.k_input_value_err,select.k_input_value_err{border:1px dashed #FF6E00 !important;}"
            + ".clearfix {*zoom:1;}.clearfix:before,.clearfix:after{display:table;line-height:0;content:'';} .clearfix:after{clear:both;}::-webkit-scrollbar{width:8px;height:8px;}::-webkit-scrollbar-button,::-webkit-scrollbar-button:vertical{display:none;}"
            + "::-webkit-scrollbar-track,::-webkit-scrollbar-track:vertical{box-shadow:inset006pxtransparent;background-color:transparent;}::-webkit-scrollbar-thumb,::-webkit-scrollbar-thumb:vertical{box-shadow:inset006pxrgba(100,173,250,.5);border-radius:6px;}"
            + "::-webkit-scrollbar-thumb:hover,::-webkit-scrollbar-thumb:vertical:hover{box-shadow:inset006pxrgba(100,173,250,.8);background-color:#74B9FF;}::-webkit-scrollbar-corner,::-webkit-scrollbar-corner:vertical{background-color:none;}"
            + "::-webkit-scrollbar-resizer,::-webkit-scrollbar-resizer:vertical{background-color:#ff6e00;}.ifr_inner_delbtn{position:relative;top:-5px;left:5px;}.ifr_inner_delbtn:before{content:'x';font-weight: bold;}"
            + 'select{border: solid 1px #ccc; appearance:none;-moz-appearance:none;-webkit-appearance: none;padding: 2px 12px 2px 2px;background: url("") no-repeat scroll right center transparent;}select::-ms-expand {display: none;}'
            + "input[type=text],input[type=password] {-webkit-appearance: textfield;background-color: white;-webkit-rtl-ordering: logical;user-select: text;cursor: auto;padding: 3px 2px;outline: none;border: 1px solid #ccc;line-height: 18px;box-sizing: border-box;font-size:13px;}");
        if (style) {
            let userStyle = style;
            if (Array.isArray(style)) {
                userStyle = style.join("");
            }
            this._appendHeaderStyle($head, "userstyle", userStyle);
        }
    },
    clearDomSelected: function () {
        try {
            if (document.selection) {
                document.selection.empty();
            } else if (window.getSelection) {
                window.getSelection().removeAllRanges();
            }
        } catch (r) { }
    },
    getInputVal: function (el, defVal) {
        let v = $B.trimFn(el.value);
        if (v === "" && typeof defVal !== "undefined") {
            return defVal
        }
        return v;
    },
    setSelectValue: function (el, val) {
        val = val + "";
        let childs = el.children;
        for (let i = 0; i < childs.length; i++) {
            if (childs[i].value === val) {
                $B.Dom.attr(childs[i], { selected: "selected" });
            } else {
                $B.Dom.removeAttr(childs[i], "selected");
            }
        }
    },
    /**
     * 按大写分隔字符，
     * splitStr：分隔符，空则返回数组
     * ***/
    splitByUper:function(txt,splitStr){
        let res;
        if(splitStr){
            res = txt.replace(/([A-Z])/g, splitStr+'$1').toLowerCase();
        }else{
            res = txt.split(/(?=[A-Z])/);
            for(let i =0 ;i < res.length;i++){
                res[i] = res[i].toLowerCase();
            }
        }
        return res;
    },
    str2camal:function(txt,splitStr){
        if(!splitStr){
            splitStr = "-";
        }
        let arr = txt.split(splitStr);
        for(let i = 0 ;i < arr.length ;i++){
            arr[i] = arr[i].toLowerCase();
            if(i > 0){
                arr[i] = arr[i].replace(/( |^)[a-z]/g,(L)=>L.toUpperCase());
            }
        }
        return arr.join("");
    }
});
/******定义一个基类
 * 封装基本的删除，情况，设置控件element的api
 * ******/
class BaseControl {
    constructor() {
        //console.log("BaseControl has bean call");
        this.id = $B.getUUID();
    }
    setElObj(args) {
        if (typeof args === "string") {
            args = args.replace("#", "");
            this.elObj = document.getElementById(args);
            this.id = args;
        } else {
            this.elObj = args;
            let id = $B.DomUtils.attribute(this.elObj, "id");
            if (id) {
                this.id = id;
            } else {
                this.id = $B.getUUID();
                $B.DomUtils.attribute(this.elObj, { "id": this.id });
            }
        }
        // if (!this.id) {
        //     this.id = $B.getUUID();
        // }
    }
    clearDom() {
        if (this.elObj) {
            $B.DomUtils.removeChilds(this.elObj);
        }
    }
    delProps(excuObjName) {
        for (var p in this) {
            if (this.hasOwnProperty(p)) {
                if (this[p] !== null && this[p] !== undefined) {
                    if (p !== "super" && typeof (this[p].destroy) === "function") {
                        if (!excuObjName || excuObjName !== this[p]) {
                            this[p].destroy(this);
                        }
                    }
                }
                delete this[p];
            }
        }
    }
    destroy(excuObjName) {
        if (this.elObj) {
            $B.DomUtils.remove(this.elObj);
            this.elObj = undefined;
        }
        this.delProps(excuObjName);
    }
    clearProps() {
        for (var p in this) {
            if (this.hasOwnProperty(p)) {
                delete this[p];
            }
        }
    }
    clear() {
        this.clearDom();
        this.delProps();
    }
}
$B["BaseControl"] = BaseControl;
//设置一个用于a标签下载指向的iframe
var count = 0;
var itv001 = setTimeout(function () {
    let $body = document.body;
    if ($body) {
        clearInterval(itv001);
        if (!$B.Dom.findbyId($body, "k_down_load_ifr")) {
            let isLoadding = false;
            let ifr = $B.Dom.createEl('<iframe  name="k_down_load_ifr" id="k_down_load_ifr" frameborder="0" style="display:none;vertical-align:top;" scroll="none" width="0" height="0" ></iframe>');
            $B.Dom.append($body, ifr);
            $B.DomUtils.onload(ifr, () => {
                if (isLoadding) {
                    $B.error($B.config.file404, 2);
                }
            });
            setTimeout(function () {
                isLoadding = true;
            }, 300);
        }
    }
    count++;
    if (count > 20) {
        clearInterval(itv001);
    }
}, 300); 
 if(!window["$B"] ) {window["$B"] = $B;} 
  return window["$B"] ; 
});
